mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Refuse from CallStack for complete CallGraph
This commit is contained in:
parent
e736cf09d7
commit
30781bb16e
41
teavm-core/src/main/java/org/teavm/callgraph/CallGraph.java
Normal file
41
teavm-core/src/main/java/org/teavm/callgraph/CallGraph.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
* <p>Root object for traversing through call graph. Graph does not represent polymorphic calls.
|
||||
* Instead, it generated multiple call sites for one location.</p>
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface CallGraph {
|
||||
/**
|
||||
* <p>Get node corresponding to the specific method.</p>
|
||||
*
|
||||
* @param method a method to lookup node for.
|
||||
* @return the node that corresponds to the specified method or <code>null</code>, if this method is never
|
||||
* called.
|
||||
*/
|
||||
CallGraphNode getNode(MethodReference method);
|
||||
|
||||
Collection<? extends FieldAccessSite> getFieldAccess(FieldReference reference);
|
||||
|
||||
Collection<? extends ClassAccessSite> getClassAccess(String className);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
* Represents a method with information about what methods does it call and what method do call the method.
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface CallGraphNode {
|
||||
/*
|
||||
* Returns reference to entire call graph.
|
||||
*/
|
||||
CallGraph getGraph();
|
||||
|
||||
/**
|
||||
* Returns the method that this node represents.
|
||||
*/
|
||||
MethodReference getMethod();
|
||||
|
||||
/**
|
||||
* Returns immutable collection of all call sites that are in the method.
|
||||
*/
|
||||
Collection<? extends CallSite> getCallSites();
|
||||
|
||||
/**
|
||||
* Returns immutable collection of all call sites that call this method.
|
||||
*/
|
||||
Collection<? extends CallSite> getCallerCallSites();
|
||||
|
||||
Collection<? extends FieldAccessSite> getFieldAccessSites();
|
||||
|
||||
Collection<? extends ClassAccessSite> getClassAccessSites();
|
||||
}
|
41
teavm-core/src/main/java/org/teavm/callgraph/CallSite.java
Normal file
41
teavm-core/src/main/java/org/teavm/callgraph/CallSite.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
* <p>Call site that represents exact place in the code that calls a method.</p>.
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface CallSite {
|
||||
/**
|
||||
* <p>Gets location of the call site</p>.
|
||||
*
|
||||
* @return location of the call site or <code>null</code> if no debug information found for this call site.
|
||||
*/
|
||||
InstructionLocation getLocation();
|
||||
|
||||
/**
|
||||
* <p>Gets a method that this call site invokes.</p>
|
||||
*/
|
||||
CallGraphNode getCallee();
|
||||
|
||||
/**
|
||||
* <p>Gets a method that contains this call site.</p>
|
||||
*/
|
||||
CallGraphNode getCaller();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface ClassAccessSite {
|
||||
InstructionLocation getLocation();
|
||||
|
||||
CallGraphNode getCallee();
|
||||
|
||||
String getClassName();
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DefaultCallGraph implements CallGraph {
|
||||
private Map<MethodReference, DefaultCallGraphNode> nodes = new HashMap<>();
|
||||
private Map<FieldReference, Set<DefaultFieldAccessSite>> fieldAccessSites = new HashMap<>();
|
||||
private Map<String, Set<DefaultClassAccessSite>> classAccessSites = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public DefaultCallGraphNode getNode(MethodReference method) {
|
||||
DefaultCallGraphNode node = nodes.get(method);
|
||||
if (node == null) {
|
||||
node = new DefaultCallGraphNode(this);
|
||||
nodes.put(method, node);
|
||||
}
|
||||
return nodes.get(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DefaultFieldAccessSite> getFieldAccess(FieldReference reference) {
|
||||
Set<DefaultFieldAccessSite> resultSet = fieldAccessSites.get(reference);
|
||||
return resultSet != null ? Collections.unmodifiableSet(resultSet) :
|
||||
Collections.<DefaultFieldAccessSite>emptySet();
|
||||
}
|
||||
|
||||
void addFieldAccess(DefaultFieldAccessSite accessSite) {
|
||||
Set<DefaultFieldAccessSite> sites = fieldAccessSites.get(accessSite.getField());
|
||||
if (sites == null) {
|
||||
sites = new HashSet<>();
|
||||
fieldAccessSites.put(accessSite.getField(), sites);
|
||||
}
|
||||
sites.add(accessSite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DefaultClassAccessSite> getClassAccess(String className) {
|
||||
Set<DefaultClassAccessSite> resultSet = classAccessSites.get(className);
|
||||
return resultSet != null ? Collections.unmodifiableSet(resultSet) :
|
||||
Collections.<DefaultClassAccessSite>emptySet();
|
||||
}
|
||||
|
||||
void addClassAccess(DefaultClassAccessSite accessSite) {
|
||||
Set<DefaultClassAccessSite> sites = classAccessSites.get(accessSite.getClassName());
|
||||
if (sites == null) {
|
||||
sites = new HashSet<>();
|
||||
classAccessSites.put(accessSite.getClassName(), sites);
|
||||
}
|
||||
sites.add(accessSite);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DefaultCallGraphNode implements CallGraphNode {
|
||||
private DefaultCallGraph graph;
|
||||
private MethodReference method;
|
||||
private Set<DefaultCallSite> callSites;
|
||||
private transient Set<DefaultCallSite> safeCallSites;
|
||||
private List<DefaultCallSite> callerCallSites;
|
||||
private transient List<DefaultCallSite> safeCallersCallSites;
|
||||
private Set<DefaultFieldAccessSite> fieldAccessSites;
|
||||
private transient Set<DefaultFieldAccessSite> safeFieldAccessSites;
|
||||
private Set<DefaultClassAccessSite> classAccessSites;
|
||||
private transient Set<DefaultClassAccessSite> safeClassAccessSites;
|
||||
|
||||
DefaultCallGraphNode(DefaultCallGraph graph) {
|
||||
this.graph = graph;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultCallGraph getGraph() {
|
||||
return graph;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodReference getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DefaultCallSite> getCallSites() {
|
||||
if (safeCallSites == null) {
|
||||
safeCallSites = Collections.unmodifiableSet(callSites);
|
||||
}
|
||||
return safeCallSites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DefaultCallSite> getCallerCallSites() {
|
||||
if (safeCallersCallSites == null) {
|
||||
safeCallersCallSites = Collections.unmodifiableList(callerCallSites);
|
||||
}
|
||||
return safeCallersCallSites;
|
||||
}
|
||||
|
||||
public void addCallSite(MethodReference method, InstructionLocation location) {
|
||||
DefaultCallGraphNode callee = graph.getNode(method);
|
||||
DefaultCallSite callSite = new DefaultCallSite(location, callee, this);
|
||||
if (callSites.add(callSite)) {
|
||||
callee.callerCallSites.add(callSite);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCallSite(MethodReference method) {
|
||||
addCallSite(method, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DefaultFieldAccessSite> getFieldAccessSites() {
|
||||
if (safeFieldAccessSites == null) {
|
||||
safeFieldAccessSites = Collections.unmodifiableSet(fieldAccessSites);
|
||||
}
|
||||
return safeFieldAccessSites;
|
||||
}
|
||||
|
||||
public void addFieldAccess(FieldReference field, InstructionLocation location) {
|
||||
DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field);
|
||||
if (fieldAccessSites.add(site)) {
|
||||
graph.addFieldAccess(site);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ClassAccessSite> getClassAccessSites() {
|
||||
if (safeClassAccessSites == null) {
|
||||
safeClassAccessSites = Collections.unmodifiableSet(classAccessSites);
|
||||
}
|
||||
return safeClassAccessSites;
|
||||
}
|
||||
|
||||
public void addClassAccess(String className, InstructionLocation location) {
|
||||
DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className);
|
||||
if (classAccessSites.add(site)) {
|
||||
graph.addClassAccess(site);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DefaultCallSite implements CallSite {
|
||||
private InstructionLocation location;
|
||||
private DefaultCallGraphNode callee;
|
||||
private DefaultCallGraphNode caller;
|
||||
|
||||
DefaultCallSite(InstructionLocation location, DefaultCallGraphNode callee, DefaultCallGraphNode caller) {
|
||||
this.location = location;
|
||||
this.callee = callee;
|
||||
this.caller = caller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstructionLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultCallGraphNode getCallee() {
|
||||
return callee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultCallGraphNode getCaller() {
|
||||
return caller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof DefaultCallSite)) {
|
||||
return false;
|
||||
}
|
||||
DefaultCallSite other = (DefaultCallSite)obj;
|
||||
return Objects.equals(callee.getMethod(), other.callee.getMethod()) &&
|
||||
Objects.equals(location, other.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(callee.getMethod(), location);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DefaultClassAccessSite implements ClassAccessSite {
|
||||
private InstructionLocation location;
|
||||
private CallGraphNode callee;
|
||||
private String className;
|
||||
|
||||
DefaultClassAccessSite(InstructionLocation location, CallGraphNode callee, String className) {
|
||||
this.location = location;
|
||||
this.callee = callee;
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstructionLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallGraphNode getCallee() {
|
||||
return callee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DefaultFieldAccessSite implements FieldAccessSite {
|
||||
private InstructionLocation location;
|
||||
private CallGraphNode callee;
|
||||
private FieldReference field;
|
||||
|
||||
DefaultFieldAccessSite(InstructionLocation location, CallGraphNode callee, FieldReference field) {
|
||||
this.location = location;
|
||||
this.callee = callee;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstructionLocation getLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallGraphNode getCallee() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldReference getField() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(location, callee, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof DefaultFieldAccessSite)) {
|
||||
return false;
|
||||
}
|
||||
DefaultFieldAccessSite other = (DefaultFieldAccessSite)obj;
|
||||
return Objects.equals(location, other.location) && Objects.equals(callee, other.callee) &&
|
||||
Objects.equals(field, other.field);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.callgraph;
|
||||
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface FieldAccessSite {
|
||||
InstructionLocation getLocation();
|
||||
|
||||
CallGraphNode getCallee();
|
||||
|
||||
FieldReference getField();
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -24,13 +26,11 @@ import org.teavm.model.ClassReader;
|
|||
public class ClassDependency implements ClassDependencyInfo {
|
||||
private DependencyChecker checker;
|
||||
private String className;
|
||||
private DependencyStack stack;
|
||||
private ClassReader classReader;
|
||||
|
||||
ClassDependency(DependencyChecker checker, String className, DependencyStack stack, ClassReader classReader) {
|
||||
ClassDependency(DependencyChecker checker, String className, ClassReader classReader) {
|
||||
this.checker = checker;
|
||||
this.className = className;
|
||||
this.stack = stack;
|
||||
this.classReader = classReader;
|
||||
}
|
||||
|
||||
|
@ -48,14 +48,9 @@ public class ClassDependency implements ClassDependencyInfo {
|
|||
return classReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DependencyStack getStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public void initClass(DependencyStack stack) {
|
||||
public void initClass(MethodReference caller, InstructionLocation location) {
|
||||
if (!isMissing()) {
|
||||
checker.initClass(this, stack);
|
||||
checker.initClass(this, caller, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,4 @@ public interface ClassDependencyInfo {
|
|||
String getClassName();
|
||||
|
||||
boolean isMissing();
|
||||
|
||||
DependencyStack getStack();
|
||||
}
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.Diagnostics;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -34,11 +32,11 @@ public interface DependencyAgent extends DependencyInfo, ServiceRepository {
|
|||
|
||||
void submitClass(ClassHolder cls);
|
||||
|
||||
MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack);
|
||||
MethodDependency linkMethod(MethodReference methodRef, MethodReference caller, InstructionLocation location);
|
||||
|
||||
ClassDependency linkClass(String className, final DependencyStack stack);
|
||||
ClassDependency linkClass(String className, MethodReference caller, InstructionLocation location);
|
||||
|
||||
FieldDependency linkField(FieldReference fieldRef, DependencyStack stack);
|
||||
FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location);
|
||||
|
||||
Diagnostics getDiagnostics();
|
||||
}
|
||||
|
|
|
@ -17,8 +17,11 @@ package org.teavm.dependency;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.callgraph.DefaultCallGraph;
|
||||
import org.teavm.common.*;
|
||||
import org.teavm.common.CachedMapper.KeyListener;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.util.ModelUtils;
|
||||
|
||||
|
@ -33,9 +36,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
private ClassLoader classLoader;
|
||||
private Mapper<MethodReference, MethodReader> methodReaderCache;
|
||||
private Mapper<FieldReference, FieldReader> fieldReaderCache;
|
||||
private Map<MethodReference, DependencyStack> stacks = new HashMap<>();
|
||||
private Map<FieldReference, DependencyStack> fieldStacks = new HashMap<>();
|
||||
private Map<String, DependencyStack> classStacks = new HashMap<>();
|
||||
private CachedMapper<MethodReference, MethodDependency> methodCache;
|
||||
private CachedMapper<FieldReference, FieldDependency> fieldCache;
|
||||
private CachedMapper<String, ClassDependency> classCache;
|
||||
|
@ -51,6 +51,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
private DependencyCheckerInterruptor interruptor;
|
||||
private boolean interrupted;
|
||||
private Diagnostics diagnostics;
|
||||
private DefaultCallGraph callGraph = new DefaultCallGraph();
|
||||
|
||||
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
||||
Diagnostics diagnostics) {
|
||||
|
@ -72,26 +73,24 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
@Override public MethodDependency map(MethodReference preimage) {
|
||||
MethodReader method = methodReaderCache.map(preimage);
|
||||
if (method != null && !method.getReference().equals(preimage)) {
|
||||
stacks.put(method.getReference(), stacks.get(preimage));
|
||||
return methodCache.map(method.getReference());
|
||||
}
|
||||
return createMethodDep(preimage, method, stacks.get(preimage));
|
||||
return createMethodDep(preimage, method);
|
||||
}
|
||||
});
|
||||
fieldCache = new CachedMapper<>(new Mapper<FieldReference, FieldDependency>() {
|
||||
@Override public FieldDependency map(FieldReference preimage) {
|
||||
FieldReader field = fieldReaderCache.map(preimage);
|
||||
if (field != null && !field.getReference().equals(preimage)) {
|
||||
fieldStacks.put(field.getReference(), fieldStacks.get(preimage));
|
||||
return fieldCache.map(field.getReference());
|
||||
}
|
||||
return createFieldNode(preimage, field, fieldStacks.get(preimage));
|
||||
return createFieldNode(preimage, field);
|
||||
}
|
||||
});
|
||||
|
||||
classCache = new CachedMapper<>(new Mapper<String, ClassDependency>() {
|
||||
@Override public ClassDependency map(String preimage) {
|
||||
return createClassDependency(preimage, classStacks.get(preimage));
|
||||
return createClassDependency(preimage);
|
||||
}
|
||||
});
|
||||
methodCache.addKeyListener(new KeyListener<MethodReference>() {
|
||||
|
@ -167,7 +166,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
|
||||
@Override
|
||||
public String generateClassName() {
|
||||
return "$$tmp$$.TempClass" + classNameSuffix++;
|
||||
return "$$teavm_generated_class$$" + classNameSuffix++;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -189,7 +188,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
if (parameters.length + 1 != argumentTypes.length) {
|
||||
throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments");
|
||||
}
|
||||
MethodDependency method = linkMethod(methodRef, DependencyStack.ROOT);
|
||||
MethodDependency method = linkMethod(methodRef, null, null);
|
||||
method.use();
|
||||
DependencyNode[] varNodes = method.getVariables();
|
||||
varNodes[0].propagate(getType(methodRef.getClassName()));
|
||||
|
@ -218,7 +217,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
|
||||
@Override
|
||||
public ClassDependency linkClass(String className, DependencyStack stack) {
|
||||
classStacks.put(className, stack);
|
||||
return classCache.map(className);
|
||||
}
|
||||
|
||||
|
@ -239,21 +237,26 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack) {
|
||||
public MethodDependency linkMethod(MethodReference methodRef, MethodReference caller,
|
||||
InstructionLocation location) {
|
||||
if (methodRef == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
stacks.put(methodRef, stack);
|
||||
callGraph.addNode(methodRef);
|
||||
if (caller != null) {
|
||||
callGraph.addNode(caller);
|
||||
callGraph.getNode(caller).addCallSite(methodRef, location);
|
||||
}
|
||||
return methodCache.map(methodRef);
|
||||
}
|
||||
|
||||
void initClass(ClassDependency cls, final DependencyStack stack) {
|
||||
void initClass(ClassDependency cls, final MethodReference caller, final InstructionLocation location) {
|
||||
ClassReader reader = cls.getClassReader();
|
||||
final MethodReader method = reader.getMethod(new MethodDescriptor("<clinit>", void.class));
|
||||
if (method != null) {
|
||||
tasks.add(new Runnable() {
|
||||
@Override public void run() {
|
||||
linkMethod(method.getReference(), stack).use();
|
||||
linkMethod(method.getReference(), caller, location).use();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -373,7 +376,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public FieldDependency linkField(FieldReference fieldRef, DependencyStack stack) {
|
||||
public FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location) {
|
||||
fieldStacks.put(fieldRef, stack);
|
||||
return fieldCache.map(fieldRef);
|
||||
}
|
||||
|
@ -434,25 +437,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
return methodCache.getKnown(methodRef);
|
||||
}
|
||||
|
||||
public DependencyViolations getViolations() {
|
||||
if (dependencyViolations == null) {
|
||||
dependencyViolations = new DependencyViolations(missingMethods, missingClasses, missingFields);
|
||||
}
|
||||
return dependencyViolations;
|
||||
}
|
||||
|
||||
public void checkForViolations() {
|
||||
getViolations().checkForViolations();
|
||||
}
|
||||
|
||||
public boolean hasViolations() {
|
||||
return getViolations().hasSevereViolations();
|
||||
}
|
||||
|
||||
public void showViolations(Appendable sb) throws IOException {
|
||||
getViolations().showViolations(sb);
|
||||
}
|
||||
|
||||
public void processDependencies() {
|
||||
interrupted = false;
|
||||
int index = 0;
|
||||
|
@ -477,4 +461,8 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
public Diagnostics getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public CallGraph getCallGraph() {
|
||||
return callGraph;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
import org.teavm.common.CachedMapper;
|
||||
import org.teavm.common.Mapper;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.util.ModelUtils;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.dependency;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.teavm.callgraph.DefaultCallGraphNode;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.instructions.*;
|
||||
import org.teavm.model.util.ListingBuilder;
|
||||
|
@ -31,7 +32,8 @@ class DependencyGraphBuilder {
|
|||
private DependencyNode[] nodes;
|
||||
private DependencyNode resultNode;
|
||||
private ProgramReader program;
|
||||
private DependencyStack callerStack;
|
||||
private DefaultCallGraphNode caller;
|
||||
private InstructionLocation currentLocation;
|
||||
private ExceptionConsumer currentExceptionConsumer;
|
||||
|
||||
public DependencyGraphBuilder(DependencyChecker dependencyChecker) {
|
||||
|
@ -50,7 +52,6 @@ class DependencyGraphBuilder {
|
|||
}
|
||||
resultNode = dep.getResult();
|
||||
nodes = dep.getVariables();
|
||||
callerStack = new DependencyStack(method.getReference(), dep.getStack());
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlockReader block = program.basicBlockAt(i);
|
||||
currentExceptionConsumer = createExceptionConsumer(dep, block);
|
||||
|
@ -62,7 +63,7 @@ class DependencyGraphBuilder {
|
|||
}
|
||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||
if (tryCatch.getExceptionType() != null) {
|
||||
dependencyChecker.linkClass(tryCatch.getExceptionType(), callerStack);
|
||||
dependencyChecker.linkClass(tryCatch.getExceptionType(), caller.getMethod(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,20 +117,23 @@ class DependencyGraphBuilder {
|
|||
private final DependencyChecker checker;
|
||||
private final DependencyNode[] parameters;
|
||||
private final DependencyNode result;
|
||||
private final DependencyStack stack;
|
||||
private final DefaultCallGraphNode caller;
|
||||
private final InstructionLocation location;
|
||||
private final Set<MethodReference> knownMethods = new HashSet<>();
|
||||
private ExceptionConsumer exceptionConsumer;
|
||||
|
||||
public VirtualCallConsumer(DependencyNode node, ClassReader filterClass,
|
||||
MethodDescriptor methodDesc, DependencyChecker checker, DependencyNode[] parameters,
|
||||
DependencyNode result, DependencyStack stack, ExceptionConsumer exceptionConsumer) {
|
||||
DependencyNode result, DefaultCallGraphNode caller, InstructionLocation location,
|
||||
ExceptionConsumer exceptionConsumer) {
|
||||
this.node = node;
|
||||
this.filterClass = filterClass;
|
||||
this.methodDesc = methodDesc;
|
||||
this.checker = checker;
|
||||
this.parameters = parameters;
|
||||
this.result = result;
|
||||
this.stack = stack;
|
||||
this.caller = caller;
|
||||
this.location = location;
|
||||
this.exceptionConsumer = exceptionConsumer;
|
||||
}
|
||||
|
||||
|
@ -147,7 +151,7 @@ class DependencyGraphBuilder {
|
|||
return;
|
||||
}
|
||||
MethodReference methodRef = new MethodReference(className, methodDesc);
|
||||
MethodDependency methodDep = checker.linkMethod(methodRef, stack);
|
||||
MethodDependency methodDep = checker.linkMethod(methodRef, caller.getMethod(), location);
|
||||
if (!methodDep.isMissing() && knownMethods.add(methodRef)) {
|
||||
methodDep.use();
|
||||
DependencyNode[] targetParams = methodDep.getVariables();
|
||||
|
@ -185,7 +189,7 @@ class DependencyGraphBuilder {
|
|||
private InstructionReader reader = new InstructionReader() {
|
||||
@Override
|
||||
public void location(InstructionLocation location) {
|
||||
callerStack = new DependencyStack(callerStack.getMethod(), location, callerStack.getCause());
|
||||
currentLocation = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -200,7 +204,7 @@ class DependencyGraphBuilder {
|
|||
}
|
||||
if (cst instanceof ValueType.Object) {
|
||||
final String className = ((ValueType.Object)cst).getClassName();
|
||||
dependencyChecker.linkClass(className, callerStack);
|
||||
dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +232,7 @@ class DependencyGraphBuilder {
|
|||
public void stringConstant(VariableReader receiver, String cst) {
|
||||
nodes[receiver.getIndex()].propagate(dependencyChecker.getType("java.lang.String"));
|
||||
MethodDependency method = dependencyChecker.linkMethod(new MethodReference(String.class,
|
||||
"<init>", char[].class, void.class), callerStack);
|
||||
"<init>", char[].class, void.class), caller.getMethod(), currentLocation);
|
||||
method.use();
|
||||
}
|
||||
|
||||
|
@ -316,7 +320,7 @@ class DependencyGraphBuilder {
|
|||
nodes[receiver.getIndex()].propagate(dependencyChecker.getType("[" + itemType));
|
||||
String className = extractClassName(itemType);
|
||||
if (className != null) {
|
||||
dependencyChecker.linkClass(className, callerStack);
|
||||
dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,7 +342,7 @@ class DependencyGraphBuilder {
|
|||
nodes[receiver.getIndex()].propagate(dependencyChecker.getType(sb.toString()));
|
||||
String className = extractClassName(itemType);
|
||||
if (className != null) {
|
||||
dependencyChecker.linkClass(className, callerStack);
|
||||
dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,7 +354,7 @@ class DependencyGraphBuilder {
|
|||
@Override
|
||||
public void getField(VariableReader receiver, VariableReader instance, FieldReference field,
|
||||
ValueType fieldType) {
|
||||
FieldDependency fieldDep = dependencyChecker.linkField(field, callerStack);
|
||||
FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation);
|
||||
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
||||
fieldDep.getValue().connect(receiverNode);
|
||||
initClass(field.getClassName());
|
||||
|
@ -358,7 +362,7 @@ class DependencyGraphBuilder {
|
|||
|
||||
@Override
|
||||
public void putField(VariableReader instance, FieldReference field, VariableReader value) {
|
||||
FieldDependency fieldDep = dependencyChecker.linkField(field, callerStack);
|
||||
FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation);
|
||||
DependencyNode valueNode = nodes[value.getIndex()];
|
||||
valueNode.connect(fieldDep.getValue());
|
||||
initClass(field.getClassName());
|
||||
|
@ -420,7 +424,7 @@ class DependencyGraphBuilder {
|
|||
|
||||
private void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||
List<? extends VariableReader> arguments) {
|
||||
MethodDependency methodDep = dependencyChecker.linkMethod(method, callerStack);
|
||||
MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation);
|
||||
if (methodDep.isMissing()) {
|
||||
return;
|
||||
}
|
||||
|
@ -441,7 +445,7 @@ class DependencyGraphBuilder {
|
|||
|
||||
private void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||
List<? extends VariableReader> arguments) {
|
||||
MethodDependency methodDep = dependencyChecker.linkMethod(method, callerStack);
|
||||
MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation);
|
||||
if (methodDep.isMissing()) {
|
||||
return;
|
||||
}
|
||||
|
@ -453,7 +457,7 @@ class DependencyGraphBuilder {
|
|||
DependencyConsumer listener = new VirtualCallConsumer(nodes[instance.getIndex()],
|
||||
dependencyChecker.getClassSource().get(methodDep.getMethod().getOwnerName()),
|
||||
method.getDescriptor(), dependencyChecker, actualArgs,
|
||||
receiver != null ? nodes[receiver.getIndex()] : null, callerStack,
|
||||
receiver != null ? nodes[receiver.getIndex()] : null, caller, currentLocation,
|
||||
currentExceptionConsumer);
|
||||
nodes[instance.getIndex()].addConsumer(listener);
|
||||
}
|
||||
|
@ -462,13 +466,14 @@ class DependencyGraphBuilder {
|
|||
public void isInstance(VariableReader receiver, VariableReader value, final ValueType type) {
|
||||
String className = extractClassName(type);
|
||||
if (className != null) {
|
||||
dependencyChecker.linkClass(className, callerStack);
|
||||
dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initClass(final String className) {
|
||||
dependencyChecker.linkClass(className, callerStack).initClass(callerStack);
|
||||
dependencyChecker.linkClass(className, caller.getMethod(), currentLocation)
|
||||
.initClass(caller.getMethod(), currentLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -476,8 +481,8 @@ class DependencyGraphBuilder {
|
|||
DependencyNode valueNode = nodes[value.getIndex()];
|
||||
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
||||
valueNode.connect(receiverNode);
|
||||
dependencyChecker.linkMethod(new MethodReference("java.lang.NullPointerException",
|
||||
"<init>", ValueType.VOID), callerStack).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(NullPointerException.class, "<init>", void.class),
|
||||
caller.getMethod(), currentLocation).use();
|
||||
currentExceptionConsumer.consume(dependencyChecker.getType("java.lang.NullPointerException"));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DependencyStack {
|
||||
public static final DependencyStack ROOT = new DependencyStack();
|
||||
private MethodReference method;
|
||||
private DependencyStack cause;
|
||||
private InstructionLocation location;
|
||||
|
||||
private DependencyStack() {
|
||||
}
|
||||
|
||||
public DependencyStack(MethodReference method) {
|
||||
this(method, ROOT);
|
||||
}
|
||||
|
||||
public DependencyStack(MethodReference method, InstructionLocation location) {
|
||||
this(method, location, ROOT);
|
||||
}
|
||||
|
||||
public DependencyStack(MethodReference method, DependencyStack cause) {
|
||||
this(method, null, cause);
|
||||
}
|
||||
|
||||
public DependencyStack(MethodReference method, InstructionLocation location, DependencyStack cause) {
|
||||
if (method == null || cause == null) {
|
||||
throw new IllegalArgumentException("Arguments must not be null");
|
||||
}
|
||||
this.method = method;
|
||||
this.location = location;
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public MethodReference getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public DependencyStack getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
public InstructionLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
DependencyStack stack = this;
|
||||
while (true) {
|
||||
if (stack.method == null) {
|
||||
sb.append(" used by ROOT\n");
|
||||
break;
|
||||
} else {
|
||||
sb.append(" used by " + stack.method);
|
||||
if (stack.location != null) {
|
||||
sb.append(" : ").append(stack.location.getLine());
|
||||
}
|
||||
stack = stack.cause;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.dependency;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DependencyViolations {
|
||||
private final Set<MethodDependencyInfo> missingMethods;
|
||||
private final Set<ClassDependencyInfo> missingClasses;
|
||||
private final Set<FieldDependencyInfo> missingFields;
|
||||
|
||||
DependencyViolations(Collection<? extends MethodDependencyInfo> missingMethods,
|
||||
Collection<? extends ClassDependencyInfo> missingClasses,
|
||||
Collection<? extends FieldDependencyInfo> missingFields) {
|
||||
this.missingMethods = Collections.unmodifiableSet(new HashSet<>(missingMethods));
|
||||
this.missingClasses = Collections.unmodifiableSet(new HashSet<>(missingClasses));
|
||||
this.missingFields = Collections.unmodifiableSet(new HashSet<>(missingFields));
|
||||
}
|
||||
|
||||
public Set<MethodDependencyInfo> getMissingMethods() {
|
||||
return missingMethods;
|
||||
}
|
||||
|
||||
public Set<ClassDependencyInfo> getMissingClasses() {
|
||||
return missingClasses;
|
||||
}
|
||||
|
||||
public Set<FieldDependencyInfo> getMissingFields() {
|
||||
return missingFields;
|
||||
}
|
||||
|
||||
public boolean hasSevereViolations() {
|
||||
return !missingMethods.isEmpty() || !missingClasses.isEmpty() || !missingFields.isEmpty();
|
||||
}
|
||||
|
||||
public void checkForViolations() {
|
||||
if (!hasSevereViolations()) {
|
||||
return;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
showViolations(sb);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("StringBuilder should not throw IOException");
|
||||
}
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
|
||||
public void showViolations(Appendable sb) throws IOException {
|
||||
List<String> items = new ArrayList<>();
|
||||
Map<String, DependencyStack> stackMap = new HashMap<>();
|
||||
for (ClassDependencyInfo cls : missingClasses) {
|
||||
stackMap.put(cls.getClassName(), cls.getStack());
|
||||
items.add(cls.getClassName());
|
||||
}
|
||||
for (MethodDependencyInfo method : missingMethods) {
|
||||
stackMap.put(method.getReference().toString(), method.getStack());
|
||||
items.add(method.getReference().toString());
|
||||
}
|
||||
for (FieldDependencyInfo field : missingFields) {
|
||||
stackMap.put(field.getReference().toString(), field.getStack());
|
||||
items.add(field.getReference().toString());
|
||||
}
|
||||
Collections.sort(items);
|
||||
sb.append("Can't compile due to the following violations:\n");
|
||||
for (String item : items) {
|
||||
sb.append("Missing ").append(item).append("\n");
|
||||
DependencyStack stack = stackMap.get(item);
|
||||
if (stack == null) {
|
||||
sb.append(" at unknown location\n");
|
||||
} else {
|
||||
while (stack.getMethod() != null) {
|
||||
sb.append(" at ").append(stack.getMethod().toString());
|
||||
if (stack.getLocation() != null) {
|
||||
sb.append(":").append(String.valueOf(stack.getLocation().getLine()));
|
||||
}
|
||||
sb.append("\n");
|
||||
stack = stack.getCause();
|
||||
}
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,4 @@ public interface FieldDependencyInfo {
|
|||
FieldReference getReference();
|
||||
|
||||
boolean isMissing();
|
||||
|
||||
DependencyStack getStack();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,4 @@ public interface MethodDependencyInfo {
|
|||
boolean isUsed();
|
||||
|
||||
boolean isMissing();
|
||||
|
||||
DependencyStack getStack();
|
||||
}
|
||||
|
|
|
@ -13,26 +13,24 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.dependency;
|
||||
package org.teavm.diagnostics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.teavm.model.Diagnostics;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.vm.DiagnosticsProblem;
|
||||
import org.teavm.vm.DiagnosticsProblemSeverity;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
class DependencyDiagnostics implements Diagnostics {
|
||||
private List<DiagnosticsProblem> problems = new ArrayList<>();
|
||||
private List<DiagnosticsProblem> severeProblems = new ArrayList<>();
|
||||
private List<Problem> problems = new ArrayList<>();
|
||||
private List<Problem> severeProblems = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void error(InstructionLocation location, String error) {
|
||||
DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.ERROR, location, error);
|
||||
public void error(MethodReference method, InstructionLocation location, String error, Object[] params) {
|
||||
Problem violation = new Problem(ProblemSeverity.ERROR, location, error);
|
||||
problems.add(violation);
|
||||
severeProblems.add(violation);
|
||||
}
|
||||
|
@ -44,7 +42,7 @@ class DependencyDiagnostics implements Diagnostics {
|
|||
|
||||
@Override
|
||||
public void warning(InstructionLocation location, String error) {
|
||||
DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.WARNING, location, error);
|
||||
Problem violation = new Problem(ProblemSeverity.WARNING, location, error);
|
||||
problems.add(violation);
|
||||
}
|
||||
|
||||
|
@ -53,11 +51,11 @@ class DependencyDiagnostics implements Diagnostics {
|
|||
warning(null, error);
|
||||
}
|
||||
|
||||
public List<DiagnosticsProblem> getProblems() {
|
||||
public List<Problem> getProblems() {
|
||||
return problems;
|
||||
}
|
||||
|
||||
public List<DiagnosticsProblem> getSevereProblems() {
|
||||
public List<Problem> getSevereProblems() {
|
||||
return severeProblems;
|
||||
}
|
||||
}
|
|
@ -13,19 +13,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model;
|
||||
package org.teavm.diagnostics;
|
||||
|
||||
import org.teavm.model.CallLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface Diagnostics {
|
||||
void error(InstructionLocation location, String error);
|
||||
void error(CallLocation location, String error, Object... params);
|
||||
|
||||
void error(String error);
|
||||
|
||||
void warning(InstructionLocation location, String error);
|
||||
|
||||
void warning(String error);
|
||||
void warning(CallLocation location, String error, Object... params);
|
||||
}
|
|
@ -13,30 +13,33 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.vm;
|
||||
package org.teavm.diagnostics;
|
||||
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import java.util.Arrays;
|
||||
import org.teavm.model.CallLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class DiagnosticsProblem {
|
||||
private DiagnosticsProblemSeverity severity;
|
||||
private InstructionLocation location;
|
||||
public class Problem {
|
||||
private ProblemSeverity severity;
|
||||
private CallLocation location;
|
||||
private String text;
|
||||
private Object[] params;
|
||||
|
||||
public DiagnosticsProblem(DiagnosticsProblemSeverity severity, InstructionLocation location, String text) {
|
||||
public Problem(ProblemSeverity severity, CallLocation location, String text, Object[] params) {
|
||||
this.severity = severity;
|
||||
this.location = location;
|
||||
this.text = text;
|
||||
this.params = Arrays.copyOf(params, params.length);
|
||||
}
|
||||
|
||||
public DiagnosticsProblemSeverity getSeverity() {
|
||||
public ProblemSeverity getSeverity() {
|
||||
return severity;
|
||||
}
|
||||
|
||||
public InstructionLocation getLocation() {
|
||||
public CallLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
|
@ -13,13 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.vm;
|
||||
package org.teavm.diagnostics;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public enum DiagnosticsProblemSeverity {
|
||||
public enum ProblemSeverity {
|
||||
ERROR,
|
||||
WARNING
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
|
|
57
teavm-core/src/main/java/org/teavm/model/CallLocation.java
Normal file
57
teavm-core/src/main/java/org/teavm/model/CallLocation.java
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class CallLocation {
|
||||
private MethodReference method;
|
||||
private InstructionLocation sourceLocation;
|
||||
|
||||
public CallLocation(MethodReference method, InstructionLocation sourceLocation) {
|
||||
this.method = method;
|
||||
this.sourceLocation = sourceLocation;
|
||||
}
|
||||
|
||||
public MethodReference getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public InstructionLocation getSourceLocation() {
|
||||
return sourceLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(method, sourceLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof CallLocation)) {
|
||||
return false;
|
||||
}
|
||||
CallLocation other = (CallLocation)obj;
|
||||
return Objects.equals(method, other.method) && Objects.equals(sourceLocation, other.sourceLocation);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Set;
|
|||
import org.teavm.dependency.ClassDependencyInfo;
|
||||
import org.teavm.dependency.FieldDependencyInfo;
|
||||
import org.teavm.dependency.MethodDependencyInfo;
|
||||
import org.teavm.diagnostics.Problem;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -32,9 +33,9 @@ public interface Violations {
|
|||
|
||||
Set<FieldDependencyInfo> getMissingFields();
|
||||
|
||||
List<DiagnosticsProblem> getDiagnosticsProblems();
|
||||
List<Problem> getDiagnosticsProblems();
|
||||
|
||||
List<DiagnosticsProblem> getSevereDiagnosticsProblems();
|
||||
List<Problem> getSevereDiagnosticsProblems();
|
||||
|
||||
boolean hasSevereViolations();
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.jso.plugin;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.javascript.ni.PreserveOriginalName;
|
||||
import org.teavm.jso.*;
|
||||
import org.teavm.model.*;
|
||||
|
|
Loading…
Reference in New Issue
Block a user