/******************************************************************************* * Copyright (c) 2009-2011 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI * * Bas Basten - Bas.Basten@cwi.nl (CWI) * * Jouke Stoel - Jouke.Stoel@cwi.nl (CWI) * * Mark Hills - Mark.Hills@cwi.nl (CWI) * * Arnold Lankamp - Arnold.Lankamp@cwi.nl *******************************************************************************/ package lang.java.jdt.internal; import static org.rascalmpl.eclipse.library.lang.java.jdt.internal.Java.ADT_ASTNODE; import static org.rascalmpl.eclipse.library.lang.java.jdt.internal.Java.ADT_ENTITY; import static org.rascalmpl.eclipse.library.lang.java.jdt.internal.Java.ADT_MODIFIER; import java.util.ArrayList; import java.util.EmptyStackException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import org.eclipse.core.resources.IFile; import org.eclipse.imp.pdb.facts.IBool; import org.eclipse.imp.pdb.facts.ISetWriter; import org.eclipse.imp.pdb.facts.ISourceLocation; import org.eclipse.imp.pdb.facts.ITuple; import org.eclipse.imp.pdb.facts.IValue; import org.eclipse.imp.pdb.facts.IValueFactory; import org.eclipse.imp.pdb.facts.type.Type; import org.eclipse.imp.pdb.facts.type.TypeFactory; import org.eclipse.imp.pdb.facts.type.TypeStore; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration; import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.BodyDeclaration; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ConstructorInvocation; import org.eclipse.jdt.core.dom.EnumConstantDeclaration; import org.eclipse.jdt.core.dom.EnumDeclaration; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.IPackageBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.Initializer; import org.eclipse.jdt.core.dom.Javadoc; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.PackageDeclaration; import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SuperConstructorInvocation; import org.eclipse.jdt.core.dom.SuperFieldAccess; import org.eclipse.jdt.core.dom.SuperMethodInvocation; import org.eclipse.jdt.core.dom.TagElement; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.TypeDeclarationStatement; import org.eclipse.jdt.core.dom.TypeParameter; import org.eclipse.jdt.core.dom.VariableDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.rascalmpl.eclipse.library.util.Resources; import org.rascalmpl.interpreter.control_exceptions.Throw; import org.rascalmpl.values.ValueFactoryFactory; // TBD: why the difference?: // entity([package("jdtimporter"),class("Activator ",[entity([typeParameter("A")])]),anonymousClass(0), method("set",[entity([package("java"),package("lang"),class("Integer")]),entity([primitive(int())])],entity([package("java"),package("lang"),class("Integer")])),parameter("element")]) // entity([package("jdtimporter"),class("Activator<A>",[entity([typeParameter("A")])]),class("new List(){}"),method("get",[ entity([primitive(int())])],entity([package("java"),package("lang"),class("Integer")])),parameter("index")]) public class JDTImporter extends ASTVisitor { protected static final IValueFactory VF = ValueFactoryFactory.getValueFactory(); protected static final TypeFactory TF = TypeFactory.getInstance(); private BindingConverter bindingCache = new BindingConverter(); private Stack<ITypeBinding> typeStack = new Stack<ITypeBinding>(); private Stack<ASTNode> scopeStack = new Stack<ASTNode>(); // only types, // methods and // initializers private IFile file; private ISourceLocation loc; // bindings private static final Type locType = TF.sourceLocationType(); private static final Type bindingTupleType = TF.tupleType(locType, ADT_ENTITY); private ISetWriter typeBindings; private ISetWriter classBindings; private ISetWriter interfaceBindings; private ISetWriter enumBindings; private ISetWriter methodBindings; private ISetWriter methodDecls; private ISetWriter fieldDecls; private ISetWriter constructorBindings; private ISetWriter fieldBindings; private ISetWriter variableBindings; private ISetWriter packageBindings; // type facts private static final Type entityTupleType = TF.tupleType(ADT_ENTITY, "from", ADT_ENTITY, "to"); private static final Type modifierTupleType = TF.tupleType(ADT_ENTITY, "entity", ADT_MODIFIER, "modifier"); private static final Type astNodeTupleType = TF.tupleType(ADT_ENTITY, "method", ADT_ASTNODE, "body"); private ISetWriter extnds; private ISetWriter implmnts; private ISetWriter declaredMethods; private ISetWriter declaredFields; private ISetWriter declaredSubTypes; private ISetWriter declaredTopTypes; private ISetWriter calls; private ISetWriter modifiers; private ISetWriter methodBodies; private final TypeStore typeStore; private CompilationUnit compilationUnit; private final boolean gatherASTs; private final boolean fillASTBindings; private final boolean fillOldStyleUsage; public JDTImporter(final TypeStore typeStore, IBool gatherASTs, IBool fillASTBindings, IBool fillOldStyleUsage) { super(); this.typeStore = typeStore; this.gatherASTs = gatherASTs.getValue(); this.fillASTBindings = fillASTBindings.getValue(); this.fillOldStyleUsage = fillOldStyleUsage.getValue(); } public Map<String, IValue> importFacts(ISourceLocation loc, IFile file) { typeBindings = VF.relationWriter(bindingTupleType); classBindings = VF.relationWriter(bindingTupleType); interfaceBindings = VF.relationWriter(bindingTupleType); enumBindings = VF.relationWriter(bindingTupleType); methodBindings = VF.relationWriter(bindingTupleType); methodDecls = VF.relationWriter(bindingTupleType); fieldDecls = VF.relationWriter(bindingTupleType); constructorBindings = VF.relationWriter(bindingTupleType); fieldBindings = VF.relationWriter(bindingTupleType); variableBindings = VF.relationWriter(bindingTupleType); packageBindings = VF.relationWriter(bindingTupleType); declaredTopTypes = VF.setWriter(ADT_ENTITY); implmnts = VF.relationWriter(entityTupleType); extnds = VF.relationWriter(entityTupleType); declaredSubTypes = VF.relationWriter(entityTupleType); declaredMethods = VF.relationWriter(entityTupleType); declaredFields = VF.relationWriter(entityTupleType); calls = VF.relationWriter(entityTupleType); methodBodies = VF.relationWriter(astNodeTupleType); modifiers = VF.relationWriter(modifierTupleType); this.loc = loc; this.file = file; visitCompilationUnit(); Map<String, IValue> facts = new HashMap<String, IValue>(); facts.put("types", typeBindings.done()); facts.put("methods", methodBindings.done()); facts.put("methodDecls", methodDecls.done()); facts.put("constructors", constructorBindings.done()); facts.put("fields", fieldBindings.done()); facts.put("fieldDecls", fieldDecls.done()); facts.put("variables", variableBindings.done()); facts.put("packages", packageBindings.done()); facts.put("classes", classBindings.done()); facts.put("interfaces", interfaceBindings.done()); facts.put("enums", enumBindings.done()); facts.put("declaredTopTypes", declaredTopTypes.done()); facts.put("implements", implmnts.done()); facts.put("extends", extnds.done()); facts.put("declaredSubTypes", declaredSubTypes.done()); facts.put("declaredMethods", declaredMethods.done()); facts.put("declaredFields", declaredFields.done()); facts.put("calls", calls.done()); facts.put("methodBodies", methodBodies.done()); facts.put("modifiers", modifiers.done()); return facts; } private void visitCompilationUnit() { int i; ICompilationUnit icu = JavaCore.createCompilationUnitFrom(file); ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setResolveBindings(true); parser.setSource(icu); compilationUnit = (CompilationUnit) parser.createAST(null); IProblem[] problems = compilationUnit.getProblems(); for (i = 0; i < problems.length; i++) { if (problems[i].isError()) { int offset = problems[i].getSourceStart(); int length = problems[i].getSourceEnd() - offset; int sl = problems[i].getSourceLineNumber(); ISourceLocation pos = VF.sourceLocation(loc.getURI(), offset, length, sl, sl, 0, 0); throw new Throw(VF.string("Error(s) in compilation unit: " + problems[i].getMessage()), pos, null); } } compilationUnit.accept(this); } public void preVisit(ASTNode n) { importBindingInfo(n); importTypeInfo(n); importCalls(n); manageStacks(n, true); } public void postVisit(ASTNode n) { manageStacks(n, false); } private void manageStacks(ASTNode n, boolean push) { // push == false -> pop ITypeBinding tb = null; boolean isScope = false; tb = getBindingOfTypeScope(n); if (tb != null) { if (push) { typeStack.push(tb); bindingCache.pushInitializerCounterStack(); bindingCache.pushAnonymousClassCounterStack(); } else { typeStack.pop(); bindingCache.popInitializerCounterStack(); bindingCache.popAnonymousClassCounterStack(); } isScope = true; } else { if (getEntityOfMethodScope(n) != null) { isScope = true; } } if (isScope) { if (push) { scopeStack.push(n); bindingCache.pushAnonymousClassCounterStack(); } else { scopeStack.pop(); bindingCache.popAnonymousClassCounterStack(); } return; } } private ITypeBinding getBindingOfTypeScope(ASTNode n) { if (n instanceof TypeDeclaration) { return ((TypeDeclaration) n).resolveBinding(); } else if (n instanceof TypeDeclarationStatement) { return ((TypeDeclarationStatement) n).getDeclaration().resolveBinding(); } else if (n instanceof AnonymousClassDeclaration) { return ((AnonymousClassDeclaration) n).resolveBinding(); } else if (n instanceof EnumDeclaration) { return ((EnumDeclaration) n).resolveBinding(); } else if (n instanceof AnnotationTypeDeclaration) { return ((AnnotationTypeDeclaration) n).resolveBinding(); } return null; } private IValue getEntityOfMethodScope(ASTNode n) { if (n instanceof MethodDeclaration) { return bindingCache.getEntity(((MethodDeclaration) n).resolveBinding()); } else if (n instanceof Initializer) { return bindingCache.getEntity((Initializer) n); } return null; } private void importBindingInfo(ASTNode n) { // type bindings ITypeBinding tb = null; if (n instanceof org.eclipse.jdt.core.dom.Type) { tb = ((org.eclipse.jdt.core.dom.Type) n).resolveBinding(); } else if (n instanceof AbstractTypeDeclaration) { tb = ((AbstractTypeDeclaration) n).resolveBinding(); } else if (n instanceof AnonymousClassDeclaration) { tb = ((AnonymousClassDeclaration) n).resolveBinding(); } else if (n instanceof Expression) { tb = ((Expression) n).resolveTypeBinding(); } else if (n instanceof TypeDeclarationStatement) { tb = ((TypeDeclarationStatement) n).resolveBinding(); } else if (n instanceof TypeParameter) { tb = ((TypeParameter) n).resolveBinding(); } else if (n instanceof EnumDeclaration) { tb = ((EnumDeclaration) n).resolveBinding(); } else if (n instanceof AnnotationTypeDeclaration) { tb = ((AnnotationTypeDeclaration) n).resolveBinding(); } if (tb != null) { Initializer possibleParent = null; try { ASTNode scope = scopeStack.peek(); if (scope instanceof Initializer) { possibleParent = (Initializer) scope; } } catch (EmptyStackException e) { // ignore } if (fillOldStyleUsage) { addBinding(typeBindings, n, bindingCache.getEntity(tb, possibleParent)); } } // method and constructor bindings IMethodBinding mb = null; IMethodBinding cb = null; if (n instanceof ClassInstanceCreation) { cb = ((ClassInstanceCreation) n).resolveConstructorBinding(); } else if (n instanceof ConstructorInvocation) { cb = ((ConstructorInvocation) n).resolveConstructorBinding(); } else if (n instanceof EnumConstantDeclaration) { cb = ((EnumConstantDeclaration) n).resolveConstructorBinding(); } else if (n instanceof MethodDeclaration) { mb = ((MethodDeclaration) n).resolveBinding(); } else if (n instanceof MethodInvocation) { mb = ((MethodInvocation) n).resolveMethodBinding(); // if this is a method invocation on an AnonymousClassDeclaration, // call importBindingInfo first to get declaration Entity. Expression exp = ((MethodInvocation) n).getExpression(); if (exp instanceof ClassInstanceCreation) { AnonymousClassDeclaration acdc = ((ClassInstanceCreation) exp).getAnonymousClassDeclaration(); if (acdc != null) { importBindingInfo(acdc); } } } else if (n instanceof SuperConstructorInvocation) { cb = ((SuperConstructorInvocation) n).resolveConstructorBinding(); } else if (n instanceof SuperMethodInvocation) { mb = ((SuperMethodInvocation) n).resolveMethodBinding(); } if (mb != null) { if (fillOldStyleUsage) { addBinding(methodBindings, n, bindingCache.getEntity(mb)); } if (n instanceof MethodDeclaration) { addBinding(methodDecls, n, bindingCache.getEntity(mb)); addMethodBody((MethodDeclaration) n, mb); } if (n instanceof MethodInvocation) { MethodInvocation mi = (MethodInvocation) n; int mods = mi.resolveMethodBinding().getMethodDeclaration().getModifiers(); List<IValue> modsForN = bindingCache.getModifiers(mods); if (mi.resolveMethodBinding().getMethodDeclaration().isDeprecated()) modsForN.add(BindingConverter.deprecatedModifier); for (IValue modifier : modsForN) modifiers.insert(VF.tuple(bindingCache.getEntity(mb), modifier)); } } if (cb != null && fillOldStyleUsage) { addBinding(constructorBindings, n, bindingCache.getEntity(cb)); } // field and variable bindings IVariableBinding vb = null; IVariableBinding fb = null; if (n instanceof EnumConstantDeclaration) { fb = ((EnumConstantDeclaration) n).resolveVariable(); } else if (n instanceof FieldDeclaration) { FieldDeclaration fd = (FieldDeclaration) n; for (Object vdfo : fd.fragments()) { VariableDeclarationFragment vdf = (VariableDeclarationFragment) vdfo; addBinding(fieldDecls, n, bindingCache.getEntity(vdf.resolveBinding())); } } else if (n instanceof FieldAccess) { FieldAccess fa = (FieldAccess) n; fb = fa.resolveFieldBinding(); // check for 'length' access of array object Expression exp = fa.getExpression(); if (exp.resolveTypeBinding().isArray() && fb.getName().equals("length")) { // put arrayLengthField in idStore, so it doesn't have to call // importVariableBinding() // (which cannot distinguish between 'length' access and a local // var inside an initializer). // don't include type of exp, b/c we can't do the same further // down bindingCache.put(fb.getKey(), BindingConverter.arrayLengthField); } // if the field is accessed on an AnonymousClassDeclaration, // call importBindingInfo first to get declaration Entity. if (exp instanceof ClassInstanceCreation) { AnonymousClassDeclaration acdc = ((ClassInstanceCreation) exp).getAnonymousClassDeclaration(); if (acdc != null) { importBindingInfo(acdc); } } } else if (n instanceof SuperFieldAccess) { fb = ((SuperFieldAccess) n).resolveFieldBinding(); } else if (n instanceof VariableDeclaration) { vb = ((VariableDeclaration) n).resolveBinding(); } else if (n instanceof SimpleName) { // local variable, parameter or field. SimpleName name = (SimpleName) n; IBinding b = name.resolveBinding(); if (b instanceof IVariableBinding) { vb = (IVariableBinding) b; if (vb.getDeclaringClass() != null) { // field fb = vb; vb = null; } else { // The field 'length' of an array type has no declaring // class // Let's try to distinguish between 'length' access and a // local variable/parameter ASTNode parent = n.getParent(); if (vb.getName().equals("length") && parent != null && parent instanceof QualifiedName && vb.toString().equals("public final int length")) { // assume 'length' access of array object (local // variables can't be public) // put arrayLengthField in idStore, so it doesn't have // to call importVariableBinding() // (which cannot distinguish between 'length' access and // a local var inside an initializer). // we can't get the array type of the object of which // the field was accessed bindingCache.put(vb.getKey(), BindingConverter.arrayLengthField); } } } } if (fb != null || vb != null) { Initializer possibleParent = null; try { ASTNode scope = scopeStack.peek(); if (scope instanceof Initializer) { possibleParent = (Initializer) scope; } } catch (EmptyStackException e) { // ignore } if (fb != null && fillOldStyleUsage) { addBinding(fieldBindings, n, bindingCache.getEntity(fb, possibleParent)); } if (vb != null) { addBinding(variableBindings, n, bindingCache.getEntity(vb, possibleParent)); } } // package bindings IPackageBinding pb = null; if (n instanceof PackageDeclaration) { pb = ((PackageDeclaration) n).resolveBinding(); } if (pb != null) { addBinding(packageBindings, n, bindingCache.getEntity(pb)); } } private void addMethodBody(MethodDeclaration method, IMethodBinding methodBinding) { if (gatherASTs) { JdtAstToRascalAstConverter converter = new JdtAstToRascalAstConverter(VF, typeStore, bindingCache, this.fillASTBindings); converter.set(compilationUnit); converter.set(loc); method.accept(converter); ITuple relation = VF.tuple(bindingCache.getEntity(methodBinding), converter.getValue()); methodBodies.insert(relation); } } private void importTypeInfo(ASTNode n) { ITypeBinding tb = null; if (n instanceof TypeDeclaration) { tb = ((TypeDeclaration) n).resolveBinding(); } if (n instanceof TypeDeclarationStatement) { tb = ((TypeDeclarationStatement) n).getDeclaration().resolveBinding(); } if (n instanceof AnonymousClassDeclaration) { tb = ((AnonymousClassDeclaration) n).resolveBinding(); } if (n instanceof EnumDeclaration) { tb = ((EnumDeclaration) n).resolveBinding(); } if (tb != null) { importTypeInfo(tb); if (tb.isClass()) addBinding(classBindings, n, bindingCache.getEntity(tb)); else if (tb.isInterface()) addBinding(interfaceBindings, n, bindingCache.getEntity(tb)); else if (tb.isEnum()) addBinding(enumBindings, n, bindingCache.getEntity(tb)); } // EnumDeclaration // EnumConstantDeclaration // FieldDeclaration // MethodDeclaration // Initializer if (n instanceof Initializer) { Initializer init = (Initializer) n; ITypeBinding parentType = typeStack.peek(); if (parentType != null) { ITuple tup = VF.tuple(bindingCache.getEntity(parentType), bindingCache.getEntity(init, parentType)); declaredMethods.insert(tup); } else { System.err.println("dangling initializer " + init.toString()); } } if (n instanceof BodyDeclaration) { List<IValue> owners = new ArrayList<IValue>(); if (n instanceof AbstractTypeDeclaration) { owners.add(bindingCache.getEntity(((AbstractTypeDeclaration) n).resolveBinding())); } else if (n instanceof AnnotationTypeMemberDeclaration) { owners.add(bindingCache.getEntity(((AnnotationTypeMemberDeclaration) n).resolveBinding())); } else if (n instanceof Initializer) { owners.add(bindingCache.getEntity((Initializer) n)); } else if (n instanceof MethodDeclaration) { owners.add(bindingCache.getEntity(((MethodDeclaration) n).resolveBinding())); } else if (n instanceof FieldDeclaration) { for (Object fragment : ((FieldDeclaration) n).fragments()) { owners.add(bindingCache.getEntity(((VariableDeclarationFragment) fragment).resolveBinding())); } } else if (n instanceof EnumConstantDeclaration) { owners.add(bindingCache.getEntity(((EnumConstantDeclaration) n).resolveConstructorBinding())); owners.add(bindingCache.getEntity(((EnumConstantDeclaration) n).resolveVariable())); } BodyDeclaration bd = (BodyDeclaration) n; List<IValue> modsForN = bindingCache.getModifiers(bd.modifiers()); Javadoc doc = bd.getJavadoc(); if (doc != null) { for (Object te : doc.tags()) { if (TagElement.TAG_DEPRECATED.equals(((TagElement) te).getTagName())) { modsForN.add(BindingConverter.deprecatedModifier); break; } } } for (IValue owner : owners) { for (IValue modifier : modsForN) { modifiers.insert(VF.tuple(owner, modifier)); } } } // method -> parameters? // method -> local variables? // throws? // modifiers? // scopes? not in JDT :( } private void importTypeInfo(ITypeBinding tb) { IValue thisType = bindingCache.getEntity(tb); if (tb.isClass()) { ITypeBinding superclass = tb.getSuperclass(); if (superclass != null) { ITuple tup = VF.tuple(thisType, bindingCache.getEntity(superclass)); extnds.insert(tup); } else { extnds.insert(VF.tuple(thisType, BindingConverter.javaLangObject)); } } ITypeBinding[] interfaces = tb.getInterfaces(); if (tb.isInterface() && interfaces.length == 0) { extnds.insert(VF.tuple(thisType, BindingConverter.javaLangObject)); } else { for (ITypeBinding interf : interfaces) { ITuple tup = VF.tuple(thisType, bindingCache.getEntity(interf)); if (tb.isClass()) { implmnts.insert(tup); } else { extnds.insert(tup); } } } if ((tb.isClass() || tb.isInterface() || tb.isEnum()) && tb.getDeclaringClass() == null) { declaredTopTypes.insert(thisType); } // doesn't include anonymous classes ITypeBinding[] innertypes = tb.getDeclaredTypes(); for (ITypeBinding innertype : innertypes) { ITuple tup = VF.tuple(thisType, bindingCache.getEntity(innertype)); declaredSubTypes.insert(tup); } // doesn't include initializers // these are added in importTypeInfo(ASTNode n) IMethodBinding[] methods = tb.getDeclaredMethods(); for (IMethodBinding method : methods) { ITuple tup = VF.tuple(thisType, bindingCache.getEntity(method)); declaredMethods.insert(tup); } IVariableBinding[] fields = tb.getDeclaredFields(); for (IVariableBinding field : fields) { ITuple tup = VF.tuple(thisType, bindingCache.getEntity(field)); declaredFields.insert(tup); } } private void importCalls(ASTNode n) { IMethodBinding mb = null; if (n instanceof MethodInvocation) { mb = ((MethodInvocation) n).resolveMethodBinding(); } else if (n instanceof ClassInstanceCreation) { mb = ((ClassInstanceCreation) n).resolveConstructorBinding(); } else if (n instanceof ConstructorInvocation) { mb = ((ConstructorInvocation) n).resolveConstructorBinding(); } else if (n instanceof SuperConstructorInvocation) { mb = ((SuperConstructorInvocation) n).resolveConstructorBinding(); } else if (n instanceof SuperMethodInvocation) { mb = ((SuperMethodInvocation) n).resolveMethodBinding(); } if (mb != null) { IValue callee = bindingCache.getEntity(mb); IValue caller = null; if (scopeStack.size() > 0) { ASTNode scope = scopeStack.peek(); ITypeBinding tb = getBindingOfTypeScope(scope); if (tb != null) { caller = bindingCache.getEntity(tb); } else { caller = getEntityOfMethodScope(scope); } } else { // should not happen } if (caller != null) { calls.insert(VF.tuple(caller, callee)); } } } private void addBinding(ISetWriter rw, ASTNode n, IValue entity) { ISourceLocation fileLoc = new Resources(VF).makeFile(file); int start = n.getStartPosition(); int end = start + n.getLength() - 1; int lineNumber = compilationUnit.getLineNumber(start); int columnNumber = compilationUnit.getColumnNumber(start); int endLineNumber = compilationUnit.getLineNumber(end); int endColumnNumber = compilationUnit.getColumnNumber(end); ISourceLocation loc = VF.sourceLocation(fileLoc.getURI(), start, n.getLength(), lineNumber, endLineNumber, columnNumber, endColumnNumber); rw.insert(VF.tuple(loc, entity)); } }