diff --git a/java/src/processing/mode/java/CompletionGenerator.java b/java/src/processing/mode/java/CompletionGenerator.java index c3528854c..82ae41b3d 100644 --- a/java/src/processing/mode/java/CompletionGenerator.java +++ b/java/src/processing/mode/java/CompletionGenerator.java @@ -24,10 +24,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -124,79 +121,82 @@ public class CompletionGenerator { return null; } - /** - * Find the parent of the expression in a().b, this would give me the return - * type of a(), so that we can find all children of a() beginning with b - */ - public static ASTNode resolveExpression(ASTNode nearestNode, - ASTNode expression, boolean noCompare) { - log("Resolving " + getNodeAsString(expression) + " noComp " - + noCompare); - if (expression instanceof SimpleName) { - return findDeclaration2(((SimpleName) expression), nearestNode); - } else if (expression instanceof MethodInvocation) { - log("3. Method Invo " - + ((MethodInvocation) expression).getName()); - return findDeclaration2(((MethodInvocation) expression).getName(), - nearestNode); - } else if (expression instanceof FieldAccess) { - log("2. Field access " - + getNodeAsString(((FieldAccess) expression).getExpression()) + "|||" - + getNodeAsString(((FieldAccess) expression).getName())); - if (noCompare) { - /* - * ASTNode ret = findDeclaration2(((FieldAccess) expression).getName(), - * nearestNode); log("Found as ->"+getNodeAsString(ret)); - * return ret; - */ - return findDeclaration2(((FieldAccess) expression).getName(), - nearestNode); - } else { - /* - * Note how for the next recursion, noCompare is reversed. Let's say - * I've typed getABC().quark.nin where nin is incomplete(ninja being the - * field), when execution first enters here, it calls resolveExpr again - * for "getABC().quark" where we know that quark field must be complete, - * so we toggle noCompare. And kaboom. - */ - return resolveExpression(nearestNode, - ((FieldAccess) expression).getExpression(), - true); - } - //return findDeclaration2(((FieldAccess) expression).getExpression(), nearestNode); - } else if (expression instanceof QualifiedName) { - log("1. Resolving " - + ((QualifiedName) expression).getQualifier() + " ||| " - + ((QualifiedName) expression).getName()); - if (noCompare) { // no compare, as in "abc.hello." need to resolve hello here - return findDeclaration2(((QualifiedName) expression).getName(), - nearestNode); - } else { - //User typed "abc.hello.by" (bye being complete), so need to resolve "abc.hello." only - return findDeclaration2(((QualifiedName) expression).getQualifier(), - nearestNode); - } - } +// /** +// * Find the parent of the expression in a().b, this would give me the return +// * type of a(), so that we can find all children of a() beginning with b +// */ +// public static ASTNode resolveExpression(ASTNode nearestNode, +// ASTNode expression, boolean noCompare) { +// log("Resolving " + getNodeAsString(expression) + " noComp " +// + noCompare); +// if (expression instanceof SimpleName) { +// return findDeclaration2(((SimpleName) expression), nearestNode); +// } else if (expression instanceof MethodInvocation) { +// log("3. Method Invo " +// + ((MethodInvocation) expression).getName()); +// return findDeclaration2(((MethodInvocation) expression).getName(), +// nearestNode); +// } else if (expression instanceof FieldAccess) { +// log("2. Field access " +// + getNodeAsString(((FieldAccess) expression).getExpression()) + "|||" +// + getNodeAsString(((FieldAccess) expression).getName())); +// if (noCompare) { +// /* +// * ASTNode ret = findDeclaration2(((FieldAccess) expression).getName(), +// * nearestNode); log("Found as ->"+getNodeAsString(ret)); +// * return ret; +// */ +// return findDeclaration2(((FieldAccess) expression).getName(), +// nearestNode); +// } else { +// +// /* +// * Note how for the next recursion, noCompare is reversed. Let's say +// * I've typed getABC().quark.nin where nin is incomplete(ninja being the +// * field), when execution first enters here, it calls resolveExpr again +// * for "getABC().quark" where we know that quark field must be complete, +// * so we toggle noCompare. And kaboom. +// */ +// return resolveExpression(nearestNode, +// ((FieldAccess) expression).getExpression(), +// true); +// } +// //return findDeclaration2(((FieldAccess) expression).getExpression(), nearestNode); +// } else if (expression instanceof QualifiedName) { +// log("1. Resolving " +// + ((QualifiedName) expression).getQualifier() + " ||| " +// + ((QualifiedName) expression).getName()); +// if (noCompare) { // no compare, as in "abc.hello." need to resolve hello here +// return findDeclaration2(((QualifiedName) expression).getName(), +// nearestNode); +// } else { +// //User typed "abc.hello.by" (bye being complete), so need to resolve "abc.hello." only +// return findDeclaration2(((QualifiedName) expression).getQualifier(), +// nearestNode); +// } +// } +// +// return null; +// } - return null; - } /** * Finds the type of the expression in foo.bar().a().b, this would give me the * type of b if it exists in return type of a(). If noCompare is true, * it'll return type of a() */ - public static ClassMember resolveExpression3rdParty(PreprocSketch ps, ASTNode nearestNode, + static public ClassMember resolveExpression3rdParty(PreprocSketch ps, ASTNode nearestNode, ASTNode astNode, boolean noCompare) { log("Resolve 3rdParty expr-- " + getNodeAsString(astNode) + " nearest node " + getNodeAsString(nearestNode)); - if(astNode == null) return null; + if (astNode == null) return null; + ClassMember scopeParent; SimpleType stp; - if(astNode instanceof SimpleName){ + if (astNode instanceof SimpleName){ ASTNode decl = findDeclaration2(((SimpleName)astNode),nearestNode); - if(decl != null){ + if (decl != null) { // see if locally defined log(getNodeAsString(astNode)+" found decl -> " + getNodeAsString(decl)); @@ -225,14 +225,12 @@ public class CompletionGenerator { // Convert element class to array class Class arrayClass = getArrayClass(name, ps.classLoader); - return arrayClass == null ? null : new ClassMember(arrayClass); } } - return new ClassMember(ps, extracTypeInfo(decl)); - } - else { + + } else { // or in a predefined class? Class tehClass = findClassIfExists(ps, astNode.toString()); if (tehClass != null) { @@ -241,14 +239,13 @@ public class CompletionGenerator { } astNode = astNode.getParent(); } + switch (astNode.getNodeType()) { //TODO: Notice the redundancy in the 3 cases, you can simplify things even more. case ASTNode.FIELD_ACCESS: FieldAccess fa = (FieldAccess) astNode; if (fa.getExpression() == null) { - // TODO: Check for existence of 'new' keyword. Could be a ClassInstanceCreation - // Local code or belongs to super class log("FA,Not implemented."); return null; @@ -371,6 +368,7 @@ public class CompletionGenerator { } break; + case ASTNode.QUALIFIED_NAME: QualifiedName qn = (QualifiedName) astNode; ASTNode temp2 = findDeclaration2(qn.getName(), nearestNode); @@ -436,7 +434,7 @@ public class CompletionGenerator { } - public static Class getArrayClass(String elementClass, ClassLoader classLoader) { + static private Class getArrayClass(String elementClass, ClassLoader classLoader) { String name; if (elementClass.startsWith("[")) { // just add a leading "[" @@ -468,7 +466,7 @@ public class CompletionGenerator { /** * For a().abc.a123 this would return a123 */ - static public ASTNode getChildExpression(ASTNode expression) { + static private ASTNode getChildExpression(ASTNode expression) { if (expression instanceof SimpleName) { return expression; } else if (expression instanceof FieldAccess) { @@ -485,7 +483,8 @@ public class CompletionGenerator { return null; } - static public ASTNode getParentExpression(ASTNode expression) { + + static private ASTNode getParentExpression(ASTNode expression) { if (expression instanceof SimpleName) { return expression; } else if (expression instanceof FieldAccess) { @@ -506,7 +505,7 @@ public class CompletionGenerator { /** * Loads classes from .jar files in sketch classpath */ - public static List getMembersForType(PreprocSketch ps, + static public List getMembersForType(PreprocSketch ps, String typeName, String child, boolean noCompare, @@ -516,15 +515,15 @@ public class CompletionGenerator { + " in class " + typeName + " noCompare " + noCompare + " staticOnly " + staticOnly); Class probableClass = findClassIfExists(ps, typeName); - if(probableClass == null){ + if (probableClass == null) { log("In GMFT(), class not found."); return candidates; } - return getMembersForType(ps, new ClassMember(probableClass), child, noCompare, staticOnly); - + return getMembersForType(ps, new ClassMember(probableClass), child, noCompare, staticOnly); } - public static ArrayList getMembersForType(PreprocSketch ps, + + static public ArrayList getMembersForType(PreprocSketch ps, ClassMember tehClass, String childToLookFor, boolean noCompare, @@ -570,20 +569,16 @@ public class CompletionGenerator { } ArrayList superClassCandidates; - if(td.getSuperclassType() != null){ + if (td.getSuperclassType() != null) { log(getNodeAsString(td.getSuperclassType()) + " <-Looking into superclass of " + tehClass); - superClassCandidates = getMembersForType(ps, new ClassMember(ps, td - .getSuperclassType()), - childToLookFor, noCompare, staticOnly); - } - else - { + ClassMember cm = new ClassMember(ps, td.getSuperclassType()); + superClassCandidates = + getMembersForType(ps, cm, childToLookFor, noCompare, staticOnly); + } else { superClassCandidates = getMembersForType(ps, new ClassMember(Object.class), childToLookFor, noCompare, staticOnly); } - for (CompletionCandidate cc : superClassCandidates) { - candidates.add(cc); - } + candidates.addAll(superClassCandidates); return candidates; } @@ -650,7 +645,8 @@ public class CompletionGenerator { return candidates; } - private static boolean notStatic(List modifiers) { + + static private boolean notStatic(List modifiers) { for (org.eclipse.jdt.core.dom.Modifier m : modifiers) { if (m.isStatic()) return false; } @@ -662,7 +658,7 @@ public class CompletionGenerator { * Searches for the particular class in the default list of imports as well as * the Sketch classpath */ - protected static Class findClassIfExists(PreprocSketch ps, String className){ + static private Class findClassIfExists(PreprocSketch ps, String className){ if (className == null){ return null; } @@ -670,16 +666,16 @@ public class CompletionGenerator { if (className.indexOf('.') >= 0) { // Figure out what is package and what is class String[] parts = className.split("\\."); - String newClassName = parts[0]; + StringBuilder newClassName = new StringBuilder(parts[0]); int i = 1; while (i < parts.length && - ps.classPath.isPackage(newClassName)) { - newClassName = newClassName + "/" + parts[i++]; + ps.classPath.isPackage(newClassName.toString())) { + newClassName.append('/').append(parts[i++]); } while (i < parts.length) { - newClassName = newClassName + "$" + parts[i++]; + newClassName.append('$').append(parts[i++]); } - className = newClassName.replace('/', '.'); + className = newClassName.toString().replace('/', '.'); } // First, see if the classname is a fully qualified name and loads straightaway @@ -724,9 +720,9 @@ public class CompletionGenerator { } return null; }) - .filter(name -> name != null) + .filter(Objects::nonNull) .map(name -> loadClass(name, ps.classLoader)) - .filter(cls -> cls != null) + .filter(Objects::nonNull) .findAny()) .filter(Optional::isPresent) .map(Optional::get) @@ -734,7 +730,7 @@ public class CompletionGenerator { .orElse(null); } - protected static Class loadClass(String className, ClassLoader classLoader){ + static private Class loadClass(String className, ClassLoader classLoader){ Class tehClass = null; if (className != null) { try { @@ -746,7 +742,7 @@ public class CompletionGenerator { return tehClass; } - public static ClassMember definedIn3rdPartyClass(PreprocSketch ps, String className,String memberName){ + static ClassMember definedIn3rdPartyClass(PreprocSketch ps, String className,String memberName){ Class probableClass = findClassIfExists(ps, className); if (probableClass == null) { log("Couldn't load " + className); @@ -759,7 +755,8 @@ public class CompletionGenerator { } } - public static ClassMember definedIn3rdPartyClass(PreprocSketch ps, ClassMember tehClass,String memberName){ + + static ClassMember definedIn3rdPartyClass(PreprocSketch ps, ClassMember tehClass,String memberName){ if(tehClass == null) return null; log("definedIn3rdPartyClass-> Looking for " + memberName @@ -813,7 +810,7 @@ public class CompletionGenerator { } - protected static ASTNode findClosestParentNode(int lineNumber, ASTNode node) { + static private ASTNode findClosestParentNode(int lineNumber, ASTNode node) { // Base.loge("Props of " + node.getClass().getName()); for (StructuralPropertyDescriptor prop : (Iterable) node .structuralPropertiesForType()) { @@ -847,7 +844,8 @@ public class CompletionGenerator { return node; } - protected static ASTNode findClosestNode(int lineNumber, ASTNode node) { + + static private ASTNode findClosestNode(int lineNumber, ASTNode node) { log("findClosestNode to line " + lineNumber); ASTNode parent = findClosestParentNode(lineNumber, node); log("findClosestParentNode returned " + getNodeAsString(parent)); @@ -884,9 +882,9 @@ public class CompletionGenerator { /** * Fetches line number of the node in its CompilationUnit. */ - public static int getLineNumber(ASTNode node) { - return ((CompilationUnit) node.getRoot()).getLineNumber(node - .getStartPosition()); + static public int getLineNumber(ASTNode node) { + CompilationUnit cu = (CompilationUnit) node.getRoot(); + return cu.getLineNumber(node.getStartPosition()); } @@ -912,8 +910,7 @@ public class CompletionGenerator { * ASTNode for ex, and it tries its level best to locate its declaration in * the AST. It really does. */ - protected static ASTNode findDeclaration(Name findMe) { - + static protected ASTNode findDeclaration(Name findMe) { // WARNING: You're entering the Rube Goldberg territory of Experimental Mode. // To debug this code, thou must take the Recursive Leap of Faith. @@ -961,7 +958,6 @@ public class CompletionGenerator { return definedIn(declaringClass, ((MethodInvocation) parent) .getName().toString(), constrains); } - } } else { parent = parent.getParent(); // Move one up the ast. V V IMP!! @@ -1104,7 +1100,7 @@ public class CompletionGenerator { /** * A variation of findDeclaration() but accepts an alternate parent ASTNode */ - protected static ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) { + static protected ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) { ASTNode declaringClass; ASTNode parent = findMe.getParent(); ASTNode ret; @@ -1327,18 +1323,18 @@ public class CompletionGenerator { * @author quarkninja * */ - public static class ClassMember { + static class ClassMember { private Field field; private Method method; private Constructor cons; - private Class thisclass; - private String stringVal; + private Class thisClass; + private final String stringVal; private String classType; private ASTNode astNode; private ASTNode declaringNode; public ClassMember(Class m) { - thisclass = m; + thisClass = m; stringVal = "Predefined Class " + m.getName(); classType = m.getName(); } @@ -1357,11 +1353,11 @@ public class CompletionGenerator { classType = m.getType().getName(); } - public ClassMember(Constructor m) { - cons = m; - stringVal = "Cons " + " " + m.getName() + " defined in " - + m.getDeclaringClass().getName(); - } +// public ClassMember(Constructor m) { +// cons = m; +// stringVal = "Cons " + " " + m.getName() + " defined in " +// + m.getDeclaringClass().getName(); +// } public ClassMember(PreprocSketch ps, ASTNode node){ astNode = node; @@ -1380,7 +1376,7 @@ public class CompletionGenerator { if(decl == null){ // a predefined type classType = stp.getName().toString(); - thisclass = findClassIfExists(ps, classType); + thisClass = findClassIfExists(ps, classType); } else{ // a local type @@ -1390,7 +1386,7 @@ public class CompletionGenerator { } public Class getClass_() { - return thisclass; + return thisClass; } public ASTNode getDeclaringNode(){ @@ -1405,13 +1401,13 @@ public class CompletionGenerator { return method; } - public Constructor getCons() { - return cons; - } +// public Constructor getCons() { +// return cons; +// } - public ASTNode getASTNode(){ - return astNode; - } +// public ASTNode getASTNode(){ +// return astNode; +// } public String toString() { return stringVal; @@ -1426,7 +1422,7 @@ public class CompletionGenerator { /** * Find the SimpleType from FD, SVD, VDS, etc */ - public static SimpleType extracTypeInfo(ASTNode node) { + static SimpleType extracTypeInfo(ASTNode node) { if (node == null) { return null; } @@ -1456,7 +1452,7 @@ public class CompletionGenerator { } - static public Type extracTypeInfo2(ASTNode node) { + static Type extracTypeInfo2(ASTNode node) { Messages.log("* extracTypeInfo2"); if (node == null) return null; @@ -1868,7 +1864,7 @@ public class CompletionGenerator { if (expr == null) { log("Expr is null"); } else { - boolean isArray = expr.thisclass != null && expr.thisclass.isArray(); + boolean isArray = expr.thisClass != null && expr.thisClass.isArray(); boolean isSimpleType = (expr.astNode != null) && expr.astNode.getNodeType() == ASTNode.SIMPLE_TYPE; boolean isMethod = expr.method != null;