Search in sources :

Example 11 with TypeDeclaration

use of org.eclipse.jdt.core.dom.TypeDeclaration in project flux by eclipse.

the class ModifierCorrectionSubProcessor method addAbstractTypeProposals.

public static void addAbstractTypeProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
    CompilationUnit astRoot = context.getASTRoot();
    ASTNode selectedNode = problem.getCoveringNode(astRoot);
    if (selectedNode == null) {
        return;
    }
    TypeDeclaration parentTypeDecl = null;
    if (selectedNode instanceof SimpleName) {
        ASTNode parent = selectedNode.getParent();
        if (parent != null) {
            parentTypeDecl = (TypeDeclaration) parent;
        }
    } else if (selectedNode instanceof TypeDeclaration) {
        parentTypeDecl = (TypeDeclaration) selectedNode;
    }
    if (parentTypeDecl == null) {
        return;
    }
    addMakeTypeAbstractProposal(context, parentTypeDecl, proposals);
}
Also used : ICompilationUnit(org.eclipse.jdt.core.ICompilationUnit) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) SimpleName(org.eclipse.jdt.core.dom.SimpleName) ASTNode(org.eclipse.jdt.core.dom.ASTNode) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration)

Example 12 with TypeDeclaration

use of org.eclipse.jdt.core.dom.TypeDeclaration in project buck by facebook.

the class JavaFileParser method extractFeaturesFromJavaCode.

public JavaFileFeatures extractFeaturesFromJavaCode(String code) {
    // For now, we will harcode this. Ultimately, we probably want to make this configurable via
    // .buckconfig. For example, the Buck project itself is diligent about disallowing wildcard
    // imports, but the one exception is the Java code generated via Thrift in src-gen.
    final boolean shouldThrowForUnsupportedWildcardImport = false;
    final AtomicBoolean isPoisonedByUnsupportedWildcardImport = new AtomicBoolean(false);
    final CompilationUnit compilationUnit = makeCompilationUnitFromSource(code);
    final ImmutableSortedSet.Builder<String> providedSymbols = ImmutableSortedSet.naturalOrder();
    final ImmutableSortedSet.Builder<String> requiredSymbols = ImmutableSortedSet.naturalOrder();
    final ImmutableSortedSet.Builder<String> exportedSymbols = ImmutableSortedSet.naturalOrder();
    final ImmutableSortedSet.Builder<String> requiredSymbolsFromExplicitImports = ImmutableSortedSet.naturalOrder();
    compilationUnit.accept(new ASTVisitor() {

        @Nullable
        private String packageName;

        /** Maps simple name to fully-qualified name. */
        private Map<String, String> simpleImportedTypes = new HashMap<>();

        /**
       * Maps wildcard import prefixes, such as {@code "java.util"} to the types in the respective
       * package if a wildcard import such as {@code import java.util.*} is used.
       */
        private Map<String, ImmutableSet<String>> wildcardImports = new HashMap<>();

        @Override
        public boolean visit(PackageDeclaration node) {
            Preconditions.checkState(packageName == null, "There should be at most one package declaration");
            packageName = node.getName().getFullyQualifiedName();
            return false;
        }

        // providedSymbols
        @Override
        public boolean visit(TypeDeclaration node) {
            // Local classes can be declared inside of methods. Skip over these.
            if (node.getParent() instanceof TypeDeclarationStatement) {
                return true;
            }
            String fullyQualifiedName = getFullyQualifiedTypeName(node);
            if (fullyQualifiedName != null) {
                providedSymbols.add(fullyQualifiedName);
            }
            @SuppressWarnings("unchecked") List<Type> interfaceTypes = node.superInterfaceTypes();
            for (Type interfaceType : interfaceTypes) {
                tryAddType(interfaceType, DependencyType.EXPORTED);
            }
            Type superclassType = node.getSuperclassType();
            if (superclassType != null) {
                tryAddType(superclassType, DependencyType.EXPORTED);
            }
            return true;
        }

        @Override
        public boolean visit(EnumDeclaration node) {
            String fullyQualifiedName = getFullyQualifiedTypeName(node);
            if (fullyQualifiedName != null) {
                providedSymbols.add(fullyQualifiedName);
            }
            return true;
        }

        @Override
        public boolean visit(AnnotationTypeDeclaration node) {
            String fullyQualifiedName = getFullyQualifiedTypeName(node);
            if (fullyQualifiedName != null) {
                providedSymbols.add(fullyQualifiedName);
            }
            return true;
        }

        // requiredSymbols
        /**
       * Uses heuristics to try to figure out what type of QualifiedName this is. Returns a non-null
       * value if this is believed to be a reference that qualifies as a "required symbol"
       * relationship.
       */
        @Override
        public boolean visit(QualifiedName node) {
            QualifiedName ancestor = findMostQualifiedAncestor(node);
            ASTNode parent = ancestor.getParent();
            if (!(parent instanceof PackageDeclaration) && !(parent instanceof ImportDeclaration)) {
                String symbol = ancestor.getFullyQualifiedName();
                // lookup.
                if (CharMatcher.javaUpperCase().matches(symbol.charAt(0))) {
                    addTypeFromDotDelimitedSequence(symbol, DependencyType.REQUIRED);
                }
            }
            return false;
        }

        /**
       * @param expr could be "Example", "Example.field", "com.example.Example". Note it could also
       *     be a built-in type, such as "java.lang.Integer", in which case it will not be added to
       *     the set of required symbols.
       */
        private void addTypeFromDotDelimitedSequence(String expr, DependencyType dependencyType) {
            // check it against JAVA_LANG_TYPES.
            if (startsWithUppercaseChar(expr)) {
                int index = expr.indexOf('.');
                if (index >= 0) {
                    String leftmostComponent = expr.substring(0, index);
                    if (JAVA_LANG_TYPES.contains(leftmostComponent)) {
                        return;
                    }
                }
            }
            expr = qualifyWithPackageNameIfNecessary(expr);
            addSymbol(expr, dependencyType);
        }

        @Override
        public boolean visit(ImportDeclaration node) {
            String fullyQualifiedName = node.getName().getFullyQualifiedName();
            // third-party code. As such, we will tolerate these for some of the common cases.
            if (node.isOnDemand()) {
                ImmutableSet<String> value = SUPPORTED_WILDCARD_IMPORTS.get(fullyQualifiedName);
                if (value != null) {
                    wildcardImports.put(fullyQualifiedName, value);
                    return false;
                } else if (shouldThrowForUnsupportedWildcardImport) {
                    throw new RuntimeException(String.format("Use of wildcard 'import %s.*' makes it impossible to statically determine " + "required symbols in this file. Please enumerate explicit imports.", fullyQualifiedName));
                } else {
                    isPoisonedByUnsupportedWildcardImport.set(true);
                    return false;
                }
            }
            // Only worry about the dependency on the enclosing type.
            Optional<String> simpleName = getSimpleNameFromFullyQualifiedName(fullyQualifiedName);
            if (simpleName.isPresent()) {
                String name = simpleName.get();
                int index = fullyQualifiedName.indexOf("." + name);
                String enclosingType = fullyQualifiedName.substring(0, index + name.length() + 1);
                requiredSymbolsFromExplicitImports.add(enclosingType);
                simpleImportedTypes.put(name, enclosingType);
            } else {
                LOG.warn("Suspicious import lacks obvious enclosing type: %s", fullyQualifiedName);
                // The one example we have seen of this in the wild is
                // "org.whispersystems.curve25519.java.curve_sigs". In practice, we still need to add it
                // as a required symbol in this case.
                requiredSymbols.add(fullyQualifiedName);
            }
            return false;
        }

        @Override
        public boolean visit(MethodInvocation node) {
            if (node.getExpression() == null) {
                return true;
            }
            String receiver = node.getExpression().toString();
            if (looksLikeAType(receiver)) {
                addTypeFromDotDelimitedSequence(receiver, DependencyType.REQUIRED);
            }
            return true;
        }

        /** An annotation on a member with zero arguments. */
        @Override
        public boolean visit(MarkerAnnotation node) {
            DependencyType dependencyType = findDependencyTypeForAnnotation(node);
            addSimpleTypeName(node.getTypeName(), dependencyType);
            return true;
        }

        /** An annotation on a member with named arguments. */
        @Override
        public boolean visit(NormalAnnotation node) {
            DependencyType dependencyType = findDependencyTypeForAnnotation(node);
            addSimpleTypeName(node.getTypeName(), dependencyType);
            return true;
        }

        /** An annotation on a member with a single, unnamed argument. */
        @Override
        public boolean visit(SingleMemberAnnotation node) {
            DependencyType dependencyType = findDependencyTypeForAnnotation(node);
            addSimpleTypeName(node.getTypeName(), dependencyType);
            return true;
        }

        private DependencyType findDependencyTypeForAnnotation(Annotation annotation) {
            ASTNode parentNode = annotation.getParent();
            if (parentNode == null) {
                return DependencyType.REQUIRED;
            }
            if (parentNode instanceof BodyDeclaration) {
                // Note that BodyDeclaration is an abstract class. Its subclasses are things like
                // FieldDeclaration and MethodDeclaration. We want to be sure that an annotation on any
                // non-private declaration is considered an exported symbol.
                BodyDeclaration declaration = (BodyDeclaration) parentNode;
                int modifiers = declaration.getModifiers();
                if ((modifiers & Modifier.PRIVATE) == 0) {
                    return DependencyType.EXPORTED;
                }
            }
            return DependencyType.REQUIRED;
        }

        @Override
        public boolean visit(SimpleType node) {
            // This method is responsible for finding the overwhelming majority of the required symbols
            // in the AST.
            tryAddType(node, DependencyType.REQUIRED);
            return true;
        }

        // exportedSymbols
        @Override
        public boolean visit(MethodDeclaration node) {
            // Types from private method signatures need not be exported.
            if ((node.getModifiers() & Modifier.PRIVATE) != 0) {
                return true;
            }
            Type returnType = node.getReturnType2();
            if (returnType != null) {
                tryAddType(returnType, DependencyType.EXPORTED);
            }
            @SuppressWarnings("unchecked") List<SingleVariableDeclaration> params = node.parameters();
            for (SingleVariableDeclaration decl : params) {
                tryAddType(decl.getType(), DependencyType.EXPORTED);
            }
            @SuppressWarnings("unchecked") List<Type> exceptions = node.thrownExceptionTypes();
            for (Type exception : exceptions) {
                tryAddType(exception, DependencyType.EXPORTED);
            }
            return true;
        }

        @Override
        public boolean visit(FieldDeclaration node) {
            // Types from private fields need not be exported.
            if ((node.getModifiers() & Modifier.PRIVATE) == 0) {
                tryAddType(node.getType(), DependencyType.EXPORTED);
            }
            return true;
        }

        private void tryAddType(Type type, DependencyType dependencyType) {
            if (type.isSimpleType()) {
                SimpleType simpleType = (SimpleType) type;
                Name simpleTypeName = simpleType.getName();
                String simpleName = simpleTypeName.toString();
                // rather than simply required.
                if (!CharMatcher.javaUpperCase().matchesAllOf(simpleName) || (dependencyType == DependencyType.EXPORTED && simpleImportedTypes.containsKey(simpleName))) {
                    addSimpleTypeName(simpleTypeName, dependencyType);
                }
            } else if (type.isArrayType()) {
                ArrayType arrayType = (ArrayType) type;
                tryAddType(arrayType.getElementType(), dependencyType);
            } else if (type.isParameterizedType()) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                tryAddType(parameterizedType.getType(), dependencyType);
                @SuppressWarnings("unchecked") List<Type> argTypes = parameterizedType.typeArguments();
                for (Type argType : argTypes) {
                    tryAddType(argType, dependencyType);
                }
            }
        }

        private void addSimpleTypeName(Name simpleTypeName, DependencyType dependencyType) {
            String simpleName = simpleTypeName.toString();
            if (JAVA_LANG_TYPES.contains(simpleName)) {
                return;
            }
            String fullyQualifiedNameForSimpleName = simpleImportedTypes.get(simpleName);
            if (fullyQualifiedNameForSimpleName != null) {
                // May need to promote from required to exported in this case.
                if (dependencyType == DependencyType.EXPORTED) {
                    addSymbol(fullyQualifiedNameForSimpleName, DependencyType.EXPORTED);
                }
                return;
            }
            // the iterator most of the time.
            if (!wildcardImports.isEmpty()) {
                for (Map.Entry<String, ImmutableSet<String>> entry : wildcardImports.entrySet()) {
                    Set<String> types = entry.getValue();
                    if (types.contains(simpleName)) {
                        String packageName = entry.getKey();
                        addSymbol(packageName + "." + simpleName, dependencyType);
                        return;
                    }
                }
            }
            String symbol = simpleTypeName.getFullyQualifiedName();
            symbol = qualifyWithPackageNameIfNecessary(symbol);
            addSymbol(symbol, dependencyType);
        }

        private void addSymbol(String symbol, DependencyType dependencyType) {
            ((dependencyType == DependencyType.REQUIRED) ? requiredSymbols : exportedSymbols).add(symbol);
        }

        private String qualifyWithPackageNameIfNecessary(String symbol) {
            if (!startsWithUppercaseChar(symbol)) {
                return symbol;
            }
            // If the symbol starts with a capital letter, then we assume that it is a reference to
            // a type in the same package.
            int index = symbol.indexOf('.');
            if (index >= 0) {
                symbol = symbol.substring(0, index);
            }
            if (packageName != null) {
                symbol = packageName + "." + symbol;
            }
            return symbol;
        }
    });
    // TODO(bolinfest): Special treatment for exportedSymbols when poisoned by wildcard import.
    ImmutableSortedSet<String> totalExportedSymbols = exportedSymbols.build();
    // If we were poisoned by an unsupported wildcard import, then we should rely exclusively on
    // the explicit imports to determine the required symbols.
    Set<String> totalRequiredSymbols = new HashSet<>();
    if (isPoisonedByUnsupportedWildcardImport.get()) {
        totalRequiredSymbols.addAll(requiredSymbolsFromExplicitImports.build());
    } else {
        totalRequiredSymbols.addAll(requiredSymbolsFromExplicitImports.build());
        totalRequiredSymbols.addAll(requiredSymbols.build());
    }
    // Make sure that required and exported symbols are disjoint sets.
    totalRequiredSymbols.removeAll(totalExportedSymbols);
    return new JavaFileFeatures(providedSymbols.build(), ImmutableSortedSet.copyOf(totalRequiredSymbols), totalExportedSymbols);
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) HashSet(java.util.HashSet) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) HashMap(java.util.HashMap) MethodInvocation(org.eclipse.jdt.core.dom.MethodInvocation) FieldDeclaration(org.eclipse.jdt.core.dom.FieldDeclaration) QualifiedName(org.eclipse.jdt.core.dom.QualifiedName) Name(org.eclipse.jdt.core.dom.Name) ArrayType(org.eclipse.jdt.core.dom.ArrayType) ParameterizedType(org.eclipse.jdt.core.dom.ParameterizedType) SimpleType(org.eclipse.jdt.core.dom.SimpleType) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) ASTNode(org.eclipse.jdt.core.dom.ASTNode) NormalAnnotation(org.eclipse.jdt.core.dom.NormalAnnotation) List(java.util.List) LinkedList(java.util.LinkedList) PackageDeclaration(org.eclipse.jdt.core.dom.PackageDeclaration) HashSet(java.util.HashSet) CompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit) Optional(java.util.Optional) SingleMemberAnnotation(org.eclipse.jdt.core.dom.SingleMemberAnnotation) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) SingleVariableDeclaration(org.eclipse.jdt.core.dom.SingleVariableDeclaration) QualifiedName(org.eclipse.jdt.core.dom.QualifiedName) AnnotationTypeDeclaration(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration) SingleMemberAnnotation(org.eclipse.jdt.core.dom.SingleMemberAnnotation) MarkerAnnotation(org.eclipse.jdt.core.dom.MarkerAnnotation) Annotation(org.eclipse.jdt.core.dom.Annotation) NormalAnnotation(org.eclipse.jdt.core.dom.NormalAnnotation) ASTVisitor(org.eclipse.jdt.core.dom.ASTVisitor) EnumDeclaration(org.eclipse.jdt.core.dom.EnumDeclaration) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ArrayType(org.eclipse.jdt.core.dom.ArrayType) ParameterizedType(org.eclipse.jdt.core.dom.ParameterizedType) SimpleType(org.eclipse.jdt.core.dom.SimpleType) Type(org.eclipse.jdt.core.dom.Type) MarkerAnnotation(org.eclipse.jdt.core.dom.MarkerAnnotation) TypeDeclarationStatement(org.eclipse.jdt.core.dom.TypeDeclarationStatement) ImportDeclaration(org.eclipse.jdt.core.dom.ImportDeclaration) BodyDeclaration(org.eclipse.jdt.core.dom.BodyDeclaration) AbstractTypeDeclaration(org.eclipse.jdt.core.dom.AbstractTypeDeclaration) AnnotationTypeDeclaration(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration) Nullable(javax.annotation.Nullable)

Example 13 with TypeDeclaration

use of org.eclipse.jdt.core.dom.TypeDeclaration in project processing by processing.

the class CompletionGenerator method preparePredictions.

/**
   * The main function that calculates possible code completion candidates
   *
   * @param pdePhrase
   * @param line
   * @param lineStartNonWSOffset
   */
public List<CompletionCandidate> preparePredictions(final PreprocessedSketch ps, final String pdePhrase, final int lineNumber) {
    Messages.log("* preparePredictions");
    ASTNode astRootNode = (ASTNode) ps.compilationUnit.types().get(0);
    // If the parsed code contains pde enhancements, take 'em out.
    // TODO: test this
    TextTransform transform = new TextTransform(pdePhrase);
    transform.addAll(SourceUtils.replaceTypeConstructors(pdePhrase));
    transform.addAll(SourceUtils.replaceHexLiterals(pdePhrase));
    transform.addAll(SourceUtils.replaceColorRegex(pdePhrase));
    transform.addAll(SourceUtils.fixFloatsRegex(pdePhrase));
    String phrase = transform.apply();
    //After typing 'arg.' all members of arg type are to be listed. This one is a flag for it
    boolean noCompare = phrase.endsWith(".");
    if (noCompare) {
        phrase = phrase.substring(0, phrase.length() - 1);
    }
    boolean incremental = !noCompare && phrase.length() > lastPredictedPhrase.length() && phrase.startsWith(lastPredictedPhrase);
    if (incremental) {
        log(pdePhrase + " starts with " + lastPredictedPhrase);
        log("Don't recalc");
        if (phrase.contains(".")) {
            int x = phrase.lastIndexOf('.');
            candidates = trimCandidates(phrase.substring(x + 1), candidates);
        } else {
            candidates = trimCandidates(phrase, candidates);
        }
        lastPredictedPhrase = phrase;
        return candidates;
    }
    // Ensure that we're not inside a comment. TODO: Binary search
    /*for (Comment comm : getCodeComments()) {
      int commLineNo = PdeToJavaLineNumber(compilationUnit
          .getLineNumber(comm.getStartPosition()));
      if(commLineNo == lineNumber){
        log("Found a comment line " + comm);
        log("Comment LSO "
            + javaCodeOffsetToLineStartOffset(compilationUnit
          .getLineNumber(comm.getStartPosition()),
                                              comm.getStartPosition()));
        break;
      }
    }*/
    // Now parse the expression into an ASTNode object
    ASTNode nearestNode;
    ASTParser parser = ASTParser.newParser(AST.JLS8);
    parser.setKind(ASTParser.K_EXPRESSION);
    parser.setSource(phrase.toCharArray());
    ASTNode testnode = parser.createAST(null);
    //Base.loge("PREDICTION PARSER PROBLEMS: " + parser);
    // Find closest ASTNode of the document to this word
    Messages.loge("Typed: " + phrase + "|" + " temp Node type: " + testnode.getClass().getSimpleName());
    if (testnode instanceof MethodInvocation) {
        MethodInvocation mi = (MethodInvocation) testnode;
        log(mi.getName() + "," + mi.getExpression() + "," + mi.typeArguments().size());
    }
    // find nearest ASTNode
    nearestNode = findClosestNode(lineNumber, astRootNode);
    if (nearestNode == null) {
        // Make sure nearestNode is not NULL if couldn't find a closest node
        nearestNode = astRootNode;
    }
    Messages.loge(lineNumber + " Nearest ASTNode to PRED " + getNodeAsString(nearestNode));
    candidates = new ArrayList<>();
    lastPredictedPhrase = phrase;
    if (testnode instanceof SimpleName && !noCompare) {
        Messages.loge("One word expression " + getNodeAsString(testnode));
        //nearestNode = nearestNode.getParent();
        while (nearestNode != null) {
            // definitions.
            if (nearestNode instanceof TypeDeclaration) {
                TypeDeclaration td = (TypeDeclaration) nearestNode;
                if (td.getStructuralProperty(TypeDeclaration.SUPERCLASS_TYPE_PROPERTY) != null) {
                    SimpleType st = (SimpleType) td.getStructuralProperty(TypeDeclaration.SUPERCLASS_TYPE_PROPERTY);
                    log("Superclass " + st.getName());
                    ArrayList<CompletionCandidate> tempCandidates = getMembersForType(ps, st.getName().toString(), phrase, false, false);
                    for (CompletionCandidate can : tempCandidates) {
                        candidates.add(can);
                    }
                //findDeclaration(st.getName())
                }
            }
            List<StructuralPropertyDescriptor> sprops = nearestNode.structuralPropertiesForType();
            for (StructuralPropertyDescriptor sprop : sprops) {
                ASTNode cnode;
                if (!sprop.isChildListProperty()) {
                    if (nearestNode.getStructuralProperty(sprop) instanceof ASTNode) {
                        cnode = (ASTNode) nearestNode.getStructuralProperty(sprop);
                        CompletionCandidate[] types = checkForTypes(cnode);
                        if (types != null) {
                            for (CompletionCandidate type : types) {
                                if (type.getElementName().toLowerCase().startsWith(phrase.toLowerCase()))
                                    candidates.add(type);
                            }
                        }
                    }
                } else {
                    // Childlist prop
                    List<ASTNode> nodelist = (List<ASTNode>) nearestNode.getStructuralProperty(sprop);
                    for (ASTNode clnode : nodelist) {
                        CompletionCandidate[] types = checkForTypes(clnode);
                        if (types != null) {
                            for (CompletionCandidate type : types) {
                                if (type.getElementName().toLowerCase().startsWith(phrase.toLowerCase()))
                                    candidates.add(type);
                            }
                        }
                    }
                }
            }
            nearestNode = nearestNode.getParent();
        }
        // We're seeing a simple name that's not defined locally or in
        // the parent class. So most probably a pre-defined type.
        log("Empty can. " + phrase);
        ClassPath classPath = ps.classPath;
        if (classPath != null) {
            RegExpResourceFilter regExpResourceFilter = new RegExpResourceFilter(Pattern.compile(".*"), Pattern.compile(phrase + "[a-zA-Z_0-9]*.class", Pattern.CASE_INSENSITIVE));
            String[] resources = classPath.findResources("", regExpResourceFilter);
            for (String matchedClass2 : resources) {
                //package name
                matchedClass2 = matchedClass2.replace('/', '.');
                String matchedClass = matchedClass2.substring(0, matchedClass2.length() - 6);
                int d = matchedClass.lastIndexOf('.');
                if (!ignorableSuggestionImport(ps, matchedClass)) {
                    //class name
                    matchedClass = matchedClass.substring(d + 1);
                    // display package name in grey
                    String html = "<html>" + matchedClass + " : <font color=#777777>" + matchedClass2.substring(0, d) + "</font></html>";
                    candidates.add(new CompletionCandidate(matchedClass, html, matchedClass, CompletionCandidate.PREDEF_CLASS));
                }
            }
        }
    } else {
        // ==> Complex expression of type blah.blah2().doIt,etc
        // Have to resolve it by carefully traversing AST of testNode
        Messages.loge("Complex expression " + getNodeAsString(testnode));
        log("candidates empty");
        ASTNode childExpr = getChildExpression(testnode);
        log("Parent expression : " + getParentExpression(testnode));
        log("Child expression : " + childExpr);
        if (!noCompare) {
            log("Original testnode " + getNodeAsString(testnode));
            testnode = getParentExpression(testnode);
            log("Corrected testnode " + getNodeAsString(testnode));
        }
        ClassMember expr = resolveExpression3rdParty(ps, nearestNode, testnode, noCompare);
        if (expr == null) {
            log("Expr is null");
        } else {
            boolean isArray = expr.thisclass != null && expr.thisclass.isArray();
            boolean isSimpleType = (expr.astNode != null) && expr.astNode.getNodeType() == ASTNode.SIMPLE_TYPE;
            boolean isMethod = expr.method != null;
            boolean staticOnly = !isMethod && !isArray && !isSimpleType;
            log("Expr is " + expr.toString());
            String lookFor = (noCompare || (childExpr == null)) ? "" : childExpr.toString();
            candidates = getMembersForType(ps, expr, lookFor, noCompare, staticOnly);
        }
    }
    return candidates;
}
Also used : ClassPath(com.google.classpath.ClassPath) SimpleName(org.eclipse.jdt.core.dom.SimpleName) MethodInvocation(org.eclipse.jdt.core.dom.MethodInvocation) SimpleType(org.eclipse.jdt.core.dom.SimpleType) RegExpResourceFilter(com.google.classpath.RegExpResourceFilter) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ArrayList(java.util.ArrayList) List(java.util.List) ASTParser(org.eclipse.jdt.core.dom.ASTParser) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration) StructuralPropertyDescriptor(org.eclipse.jdt.core.dom.StructuralPropertyDescriptor)

Example 14 with TypeDeclaration

use of org.eclipse.jdt.core.dom.TypeDeclaration in project processing by processing.

the class CompletionGenerator method findDeclaration.

/*
  protected SketchOutline sketchOutline;

  public void showSketchOutline() {
    if (editor.hasJavaTabs()) return;

    sketchOutline = new SketchOutline(editor, codeTree);
    sketchOutline.show();
  }


  public void showTabOutline() {
    new TabOutline(editor).show();
  }
  */
/**
   * Give this thing a {@link Name} instance - a {@link SimpleName} from the
   * ASTNode for ex, and it tries its level best to locate its declaration in
   * the AST. It really does.
   *
   * @param findMe
   * @return
   */
protected static 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.
    // log("entering --findDeclaration1 -- " + findMe.toString());
    ASTNode declaringClass;
    ASTNode parent = findMe.getParent();
    ASTNode ret;
    ArrayList<Integer> constrains = new ArrayList<>();
    if (parent.getNodeType() == ASTNode.METHOD_INVOCATION) {
        Expression exp = (Expression) parent.getStructuralProperty(MethodInvocation.EXPRESSION_PROPERTY);
        // Possibly a bug here. Investigate later.
        if (((MethodInvocation) parent).getName().toString().equals(findMe.toString())) {
            constrains.add(ASTNode.METHOD_DECLARATION);
            if (exp != null) {
                constrains.add(ASTNode.TYPE_DECLARATION);
                //              + exp.getClass().getName() + " parent: " + exp.getParent());
                if (exp instanceof MethodInvocation) {
                    SimpleType stp = extracTypeInfo(findDeclaration(((MethodInvocation) exp).getName()));
                    if (stp == null)
                        return null;
                    declaringClass = findDeclaration(stp.getName());
                    return definedIn(declaringClass, ((MethodInvocation) parent).getName().toString(), constrains);
                } else if (exp instanceof FieldAccess) {
                    SimpleType stp = extracTypeInfo(findDeclaration(((FieldAccess) exp).getName()));
                    if (stp == null)
                        return null;
                    declaringClass = findDeclaration((stp.getName()));
                    return definedIn(declaringClass, ((MethodInvocation) parent).getName().toString(), constrains);
                }
                if (exp instanceof SimpleName) {
                    SimpleType stp = extracTypeInfo(findDeclaration(((SimpleName) exp)));
                    if (stp == null)
                        return null;
                    declaringClass = findDeclaration(stp.getName());
                    //            log("MI.SN " + getNodeAsString(declaringClass));
                    constrains.add(ASTNode.METHOD_DECLARATION);
                    return definedIn(declaringClass, ((MethodInvocation) parent).getName().toString(), constrains);
                }
            }
        } else {
            // Move one up the ast. V V IMP!!
            parent = parent.getParent();
        }
    } else if (parent.getNodeType() == ASTNode.FIELD_ACCESS) {
        FieldAccess fa = (FieldAccess) parent;
        Expression exp = fa.getExpression();
        if (fa.getName().toString().equals(findMe.toString())) {
            constrains.add(ASTNode.FIELD_DECLARATION);
            if (exp != null) {
                constrains.add(ASTNode.TYPE_DECLARATION);
                //              + exp.getClass().getName() + " parent: " + exp.getParent());
                if (exp instanceof MethodInvocation) {
                    SimpleType stp = extracTypeInfo(findDeclaration(((MethodInvocation) exp).getName()));
                    if (stp == null)
                        return null;
                    declaringClass = findDeclaration(stp.getName());
                    return definedIn(declaringClass, fa.getName().toString(), constrains);
                } else if (exp instanceof FieldAccess) {
                    SimpleType stp = extracTypeInfo(findDeclaration(((FieldAccess) exp).getName()));
                    if (stp == null)
                        return null;
                    declaringClass = findDeclaration((stp.getName()));
                    constrains.add(ASTNode.TYPE_DECLARATION);
                    return definedIn(declaringClass, fa.getName().toString(), constrains);
                }
                if (exp instanceof SimpleName) {
                    SimpleType stp = extracTypeInfo(findDeclaration(((SimpleName) exp)));
                    if (stp == null)
                        return null;
                    declaringClass = findDeclaration(stp.getName());
                    //            log("FA.SN " + getNodeAsString(declaringClass));
                    constrains.add(ASTNode.METHOD_DECLARATION);
                    return definedIn(declaringClass, fa.getName().toString(), constrains);
                }
            }
        } else {
            // Move one up the ast. V V IMP!!
            parent = parent.getParent();
        }
    } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME) {
        QualifiedName qn = (QualifiedName) parent;
        if (!findMe.toString().equals(qn.getQualifier().toString())) {
            SimpleType stp = extracTypeInfo(findDeclaration((qn.getQualifier())));
            //        log(qn.getQualifier() + "->" + qn.getName());
            if (stp == null) {
                return null;
            }
            declaringClass = findDeclaration(stp.getName());
            //        log("QN decl class: " + getNodeAsString(declaringClass));
            constrains.clear();
            constrains.add(ASTNode.TYPE_DECLARATION);
            constrains.add(ASTNode.FIELD_DECLARATION);
            return definedIn(declaringClass, qn.getName().toString(), constrains);
        } else {
            if (findMe instanceof QualifiedName) {
                QualifiedName qnn = (QualifiedName) findMe;
                //          log("findMe is a QN, "
                //              + (qnn.getQualifier().toString() + " other " + qnn.getName()
                //                  .toString()));
                SimpleType stp = extracTypeInfo(findDeclaration((qnn.getQualifier())));
                if (stp == null) {
                    return null;
                }
                declaringClass = findDeclaration(stp.getName());
                constrains.clear();
                constrains.add(ASTNode.TYPE_DECLARATION);
                constrains.add(ASTNode.FIELD_DECLARATION);
                return definedIn(declaringClass, qnn.getName().toString(), constrains);
            }
        }
    } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE) {
        constrains.add(ASTNode.TYPE_DECLARATION);
        if (parent.getParent().getNodeType() == ASTNode.CLASS_INSTANCE_CREATION) {
            constrains.add(ASTNode.CLASS_INSTANCE_CREATION);
        }
    } else if (parent.getNodeType() == ASTNode.TYPE_DECLARATION) {
        // The condition where we look up the name of a class decl
        TypeDeclaration td = (TypeDeclaration) parent;
        if (findMe.equals(td.getName())) {
            return parent;
        }
    } else if (parent instanceof Expression) {
    //      constrains.add(ASTNode.TYPE_DECLARATION);
    //      constrains.add(ASTNode.METHOD_DECLARATION);
    //      constrains.add(ASTNode.FIELD_DECLARATION);
    }
    //    }
    while (parent != null) {
        //      log("findDeclaration1 -> " + getNodeAsString(parent));
        for (Object oprop : parent.structuralPropertiesForType()) {
            StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) oprop;
            if (prop.isChildProperty() || prop.isSimpleProperty()) {
                if (parent.getStructuralProperty(prop) instanceof ASTNode) {
                    //            log(prop + " C/S Prop of -> "
                    //                + getNodeAsString(parent));
                    ret = definedIn((ASTNode) parent.getStructuralProperty(prop), findMe.toString(), constrains);
                    if (ret != null)
                        return ret;
                }
            } else if (prop.isChildListProperty()) {
                //          log((prop) + " ChildList props of "
                //              + getNodeAsString(parent));
                List<ASTNode> nodelist = (List<ASTNode>) parent.getStructuralProperty(prop);
                for (ASTNode retNode : nodelist) {
                    ret = definedIn(retNode, findMe.toString(), constrains);
                    if (ret != null)
                        return ret;
                }
            }
        }
        parent = parent.getParent();
    }
    return null;
}
Also used : SimpleName(org.eclipse.jdt.core.dom.SimpleName) QualifiedName(org.eclipse.jdt.core.dom.QualifiedName) ArrayList(java.util.ArrayList) MethodInvocation(org.eclipse.jdt.core.dom.MethodInvocation) SimpleType(org.eclipse.jdt.core.dom.SimpleType) Expression(org.eclipse.jdt.core.dom.Expression) VariableDeclarationExpression(org.eclipse.jdt.core.dom.VariableDeclarationExpression) ASTNode(org.eclipse.jdt.core.dom.ASTNode) ArrayList(java.util.ArrayList) List(java.util.List) FieldAccess(org.eclipse.jdt.core.dom.FieldAccess) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration) StructuralPropertyDescriptor(org.eclipse.jdt.core.dom.StructuralPropertyDescriptor)

Example 15 with TypeDeclaration

use of org.eclipse.jdt.core.dom.TypeDeclaration in project processing by processing.

the class CompletionGenerator method definedIn3rdPartyClass.

public static ClassMember definedIn3rdPartyClass(PreprocessedSketch ps, ClassMember tehClass, String memberName) {
    if (tehClass == null)
        return null;
    log("definedIn3rdPartyClass-> Looking for " + memberName + " in " + tehClass);
    String memberNameL = memberName.toLowerCase();
    if (tehClass.getDeclaringNode() instanceof TypeDeclaration) {
        TypeDeclaration td = (TypeDeclaration) tehClass.getDeclaringNode();
        for (int i = 0; i < td.getFields().length; i++) {
            List<VariableDeclarationFragment> vdfs = td.getFields()[i].fragments();
            for (VariableDeclarationFragment vdf : vdfs) {
                if (vdf.getName().toString().toLowerCase().startsWith(memberNameL))
                    return new ClassMember(ps, vdf);
            }
        }
        for (int i = 0; i < td.getMethods().length; i++) {
            if (td.getMethods()[i].getName().toString().toLowerCase().startsWith(memberNameL))
                return new ClassMember(ps, td.getMethods()[i]);
        }
        if (td.getSuperclassType() != null) {
            log(getNodeAsString(td.getSuperclassType()) + " <-Looking into superclass of " + tehClass);
            return definedIn3rdPartyClass(ps, new ClassMember(ps, td.getSuperclassType()), memberName);
        } else {
            return definedIn3rdPartyClass(ps, new ClassMember(Object.class), memberName);
        }
    }
    Class<?> probableClass;
    if (tehClass.getClass_() != null) {
        probableClass = tehClass.getClass_();
    } else {
        probableClass = findClassIfExists(ps, tehClass.getTypeAsString());
        log("Loaded " + probableClass.toString());
    }
    for (Method method : probableClass.getMethods()) {
        if (method.getName().equalsIgnoreCase(memberName)) {
            return new ClassMember(method);
        }
    }
    for (Field field : probableClass.getFields()) {
        if (field.getName().equalsIgnoreCase(memberName)) {
            return new ClassMember(field);
        }
    }
    return null;
}
Also used : Field(java.lang.reflect.Field) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) Method(java.lang.reflect.Method) TypeDeclaration(org.eclipse.jdt.core.dom.TypeDeclaration)

Aggregations

TypeDeclaration (org.eclipse.jdt.core.dom.TypeDeclaration)37 ASTNode (org.eclipse.jdt.core.dom.ASTNode)24 MethodDeclaration (org.eclipse.jdt.core.dom.MethodDeclaration)21 CompilationUnit (org.eclipse.jdt.core.dom.CompilationUnit)17 AbstractTypeDeclaration (org.eclipse.jdt.core.dom.AbstractTypeDeclaration)16 ICompilationUnit (org.eclipse.jdt.core.ICompilationUnit)13 SimpleName (org.eclipse.jdt.core.dom.SimpleName)11 Type (org.eclipse.jdt.core.dom.Type)11 ArrayList (java.util.ArrayList)8 FieldDeclaration (org.eclipse.jdt.core.dom.FieldDeclaration)8 AST (org.eclipse.jdt.core.dom.AST)7 BodyDeclaration (org.eclipse.jdt.core.dom.BodyDeclaration)7 ITypeBinding (org.eclipse.jdt.core.dom.ITypeBinding)6 SimpleType (org.eclipse.jdt.core.dom.SimpleType)6 ASTRewrite (org.eclipse.jdt.core.dom.rewrite.ASTRewrite)6 List (java.util.List)5 ArrayType (org.eclipse.jdt.core.dom.ArrayType)5 PrimitiveType (org.eclipse.jdt.core.dom.PrimitiveType)5 QualifiedName (org.eclipse.jdt.core.dom.QualifiedName)5 ASTVisitor (org.eclipse.jdt.core.dom.ASTVisitor)4