public void test_metadata_typedef() throws Exception {
   Source source =
       addSource(
           createSource( //
               "const A = null;", "@A typedef F<A>();"));
   LibraryElement library = resolve(source);
   assertNotNull(library);
   CompilationUnitElement unitElement = library.getDefiningCompilationUnit();
   assertNotNull(unitElement);
   FunctionTypeAliasElement[] aliases = unitElement.getFunctionTypeAliases();
   assertLength(1, aliases);
   ElementAnnotation[] annotations = aliases[0].getMetadata();
   assertLength(1, annotations);
   assertNoErrors(source);
   verify(source);
   CompilationUnit unit = resolveCompilationUnit(source, library);
   NodeList<CompilationUnitMember> declarations = unit.getDeclarations();
   assertSizeOfList(2, declarations);
   Element expectedElement =
       ((TopLevelVariableDeclaration) declarations.get(0))
           .getVariables()
           .getVariables()
           .get(0)
           .getName()
           .getStaticElement();
   assertInstanceOf(PropertyInducingElement.class, expectedElement);
   expectedElement = ((PropertyInducingElement) expectedElement).getGetter();
   Element actualElement =
       ((FunctionTypeAlias) declarations.get(1)).getMetadata().get(0).getName().getStaticElement();
   assertSame(expectedElement, actualElement);
 }
  /**
   * Resolve the given source and verify that the arguments in a specific method invocation were
   * correctly resolved.
   *
   * <p>The source is expected to be source for a compilation unit, the first declaration is
   * expected to be a class, the first member of which is expected to be a method with a block body,
   * and the first statement in the body is expected to be an expression statement whose expression
   * is a method invocation. It is the arguments to that method invocation that are tested. The
   * method invocation can contain errors.
   *
   * <p>The arguments were resolved correctly if the number of expressions in the list matches the
   * length of the array of indices and if, for each index in the array of indices, the parameter to
   * which the argument expression was resolved is the parameter in the invoked method's list of
   * parameters at that index. Arguments that should not be resolved to a parameter because of an
   * error can be denoted by including a negative index in the array of indices.
   *
   * @param source the source to be resolved
   * @param indices the array of indices used to associate arguments with parameters
   * @throws Exception if the source could not be resolved or if the structure of the source is not
   *     valid
   */
  private void validateArgumentResolution(Source source, int... indices) throws Exception {
    LibraryElement library = resolve(source);
    assertNotNull(library);
    ClassElement classElement = library.getDefiningCompilationUnit().getTypes()[0];
    ParameterElement[] parameters = classElement.getMethods()[1].getParameters();

    CompilationUnit unit = resolveCompilationUnit(source, library);
    assertNotNull(unit);
    ClassDeclaration classDeclaration = (ClassDeclaration) unit.getDeclarations().get(0);
    MethodDeclaration methodDeclaration =
        ((MethodDeclaration) classDeclaration.getMembers().get(0));
    Block block = ((BlockFunctionBody) methodDeclaration.getBody()).getBlock();
    ExpressionStatement statement = (ExpressionStatement) block.getStatements().get(0);
    MethodInvocation invocation = (MethodInvocation) statement.getExpression();
    NodeList<Expression> arguments = invocation.getArgumentList().getArguments();

    int argumentCount = arguments.size();
    assertEquals(indices.length, argumentCount);
    for (int i = 0; i < argumentCount; i++) {
      Expression argument = arguments.get(i);
      ParameterElement element = argument.getStaticParameterElement();
      int index = indices[i];
      if (index < 0) {
        assertNull(element);
      } else {
        assertSame(parameters[index], element);
      }
    }
  }
 public void test_constructor_initializer_withParenthesizedExpression() throws Exception {
   CompilationUnit unit =
       parseCompilationUnit(
           createSource("class C {", "  C() :", "    this.a = (b == null ? c : d) {", "  }", "}"));
   NodeList<CompilationUnitMember> declarations = unit.getDeclarations();
   assertSize(1, declarations);
 }
示例#4
0
 @Override
 public Void visitCompilationUnit(CompilationUnit node) {
   ScriptTag scriptTag = node.getScriptTag();
   NodeList<Directive> directives = node.getDirectives();
   visit(scriptTag);
   String prefix = scriptTag == null ? "" : " ";
   visitList(prefix, directives, " ");
   prefix = scriptTag == null && directives.isEmpty() ? "" : " ";
   visitList(prefix, node.getDeclarations(), " ");
   return null;
 }
 private void analyzePossibleConflicts_inLibrary(
     final RefactoringStatus result, Source unitSource, Source librarySource) {
   // prepare resolved unit
   CompilationUnit unit = null;
   try {
     unit = context.resolveCompilationUnit(unitSource, librarySource);
   } catch (AnalysisException e) {
   }
   if (unit == null) {
     return;
   }
   // check for conflicts in the unit
   final SourceRange elementRange = element.getVisibleRange();
   unit.accept(
       new RecursiveAstVisitor<Void>() {
         @Override
         public Void visitSimpleIdentifier(SimpleIdentifier node) {
           Element nameElement = node.getBestElement();
           if (nameElement != null && nameElement.getName().equals(newName)) {
             // duplicate declaration
             if (haveIntersectingRanges(element, nameElement)) {
               String message =
                   MessageFormat.format(
                       "Duplicate local {0} ''{1}''.", getElementKindName(nameElement), newName);
               result.addError(message, new RefactoringStatusContext(nameElement));
               return null;
             }
             // shadowing referenced element
             if (elementRange.contains(node.getOffset()) && !node.isQualified()) {
               nameElement = HierarchyUtils.getSyntheticAccessorVariable(nameElement);
               String nameElementSourceName = nameElement.getSource().getShortName();
               String message =
                   MessageFormat.format(
                       "Usage of {0} ''{1}'' declared in ''{2}'' will be shadowed by renamed {3}.",
                       getElementKindName(nameElement),
                       getElementQualifiedName(nameElement),
                       nameElementSourceName,
                       getElementKindName(element));
               result.addError(message, new RefactoringStatusContext(node));
             }
           }
           return null;
         }
       });
 }
 public void test_localVariable_types_invoked() throws Exception {
   Source source =
       addSource(
           createSource( //
               "const A = null;",
               "main() {",
               "  var myVar = (int p) => 'foo';",
               "  myVar(42);",
               "}"));
   LibraryElement library = resolve(source);
   assertNotNull(library);
   CompilationUnit unit = getAnalysisContext().getResolvedCompilationUnit(source, library);
   assertNotNull(unit);
   final boolean[] found = {false};
   final AnalysisException[] thrownException = new AnalysisException[1];
   unit.accept(
       new RecursiveAstVisitor<Void>() {
         @Override
         public Void visitSimpleIdentifier(SimpleIdentifier node) {
           if (node.getName().equals("myVar") && node.getParent() instanceof MethodInvocation) {
             try {
               found[0] = true;
               // check static type
               Type staticType = node.getStaticType();
               assertSame(getTypeProvider().getDynamicType(), staticType);
               // check propagated type
               FunctionType propagatedType = (FunctionType) node.getPropagatedType();
               assertEquals(getTypeProvider().getStringType(), propagatedType.getReturnType());
             } catch (AnalysisException e) {
               thrownException[0] = e;
             }
           }
           return null;
         }
       });
   if (thrownException[0] != null) {
     throw new AnalysisException("Exception", thrownException[0]);
   }
   assertTrue(found[0]);
 }
 /**
  * Return the name of the library that the given part is declared to be a part of, or {@code null}
  * if the part does not contain a part-of directive.
  *
  * @param partSource the source representing the part
  * @param partUnit the AST structure of the part
  * @param directivesToResolve a list of directives that should be resolved to the library being
  *     built
  * @return the name of the library that the given part is declared to be a part of
  */
 private String getPartLibraryName(
     Source partSource, CompilationUnit partUnit, ArrayList<Directive> directivesToResolve) {
   for (Directive directive : partUnit.getDirectives()) {
     if (directive instanceof PartOfDirective) {
       directivesToResolve.add(directive);
       LibraryIdentifier libraryName = ((PartOfDirective) directive).getLibraryName();
       if (libraryName != null) {
         return libraryName.getName();
       }
     }
   }
   return null;
 }
示例#8
0
  @Override
  public void process(final Context context, final CompilationUnit unit) {
    NodeList<CompilationUnitMember> declarations = unit.getDeclarations();
    // remove NodeList, it is declared in enginelib.dart
    for (Iterator<CompilationUnitMember> iter = declarations.iterator(); iter.hasNext(); ) {
      CompilationUnitMember member = iter.next();
      if (member instanceof ClassDeclaration) {
        ClassDeclaration classDeclaration = (ClassDeclaration) member;
        String name = classDeclaration.getName().getName();
        if (name.equals("NodeList")
            || name.equals("NodeLocator")
            || name.equals("NodeFoundException")) {
          iter.remove();
        }
      }
    }
    // process nodes
    unit.accept(
        new GeneralizingASTVisitor<Void>() {
          @Override
          public Void visitMethodDeclaration(MethodDeclaration node) {
            String name = node.getName().getName();
            if ("accept".equals(name) && node.getParameters().getParameters().size() == 1) {
              node.setReturnType(null);
              FormalParameter formalParameter = node.getParameters().getParameters().get(0);
              ((SimpleFormalParameter) formalParameter).getType().setTypeArguments(null);
            }
            return super.visitMethodDeclaration(node);
          }

          @Override
          public Void visitMethodInvocation(MethodInvocation node) {
            if (isMethodInClass(
                node, "toArray", "com.google.dart.engine.utilities.collection.IntList")) {
              replaceNode(node, node.getTarget());
              return null;
            }
            return super.visitMethodInvocation(node);
          }

          @Override
          public Void visitTypeName(TypeName node) {
            if (node.getName() instanceof SimpleIdentifier) {
              SimpleIdentifier nameNode = (SimpleIdentifier) node.getName();
              String name = nameNode.getName();
              if ("IntList".equals(name)) {
                replaceNode(node, typeName("List", typeName("int")));
                return null;
              }
            }
            return super.visitTypeName(node);
          }

          private boolean isMethodInClass(
              MethodInvocation node, String reqName, String reqClassName) {
            String name = node.getMethodName().getName();
            return Objects.equal(name, reqName)
                && JavaUtils.isMethodInClass(context.getNodeBinding(node), reqClassName);
          }
        });
  }
 @Override
 public R visitCompilationUnit(CompilationUnit node) {
   node.visitChildren(this);
   return null;
 }
  public static Element getElementEnclosingOffset(CompilationUnit unit, final int offset) {
    final Element result[] = new Element[] {null};
    unit.accept(
        new GeneralizingAstVisitor<Void>() {
          @Override
          public Void visitClassDeclaration(ClassDeclaration node) {
            if (isNodeEnclosingOffset(node)) {
              result[0] = node.getElement();
              return super.visitClassDeclaration(node);
            }
            return null;
          }

          @Override
          public Void visitConstructorDeclaration(ConstructorDeclaration node) {
            if (isNodeEnclosingOffset(node)) {
              result[0] = node.getElement();
              return super.visitConstructorDeclaration(node);
            }
            return null;
          }

          @Override
          public Void visitFieldDeclaration(FieldDeclaration node) {
            if (isNodeEnclosingOffset(node)) {
              NodeList<VariableDeclaration> variables = node.getFields().getVariables();
              if (!variables.isEmpty()) {
                result[0] = variables.get(0).getElement();
              }
              return super.visitFieldDeclaration(node);
            }
            return null;
          }

          @Override
          public Void visitFunctionDeclaration(FunctionDeclaration node) {
            if (isNodeEnclosingOffset(node)) {
              result[0] = node.getElement();
              return super.visitFunctionDeclaration(node);
            }
            return null;
          }

          @Override
          public Void visitMethodDeclaration(MethodDeclaration node) {
            if (isNodeEnclosingOffset(node)) {
              result[0] = node.getElement();
              return super.visitMethodDeclaration(node);
            }
            return null;
          }

          @Override
          public Void visitNode(AstNode node) {
            if (isNodeEnclosingOffset(node)) {
              super.visitNode(node);
            }
            return null;
          }

          private boolean isNodeEnclosingOffset(AstNode node) {
            return node.getOffset() <= offset && offset <= node.getEnd();
          }
        });
    return result[0];
  }
  /**
   * Build the library element for the given library.
   *
   * @param library the library for which an element model is to be built
   * @return the library element that was built
   * @throws AnalysisException if the analysis could not be performed
   */
  public LibraryElementImpl buildLibrary(Library library) throws AnalysisException {
    CompilationUnitBuilder builder = new CompilationUnitBuilder();
    Source librarySource = library.getLibrarySource();
    CompilationUnit definingCompilationUnit = library.getDefiningCompilationUnit();
    CompilationUnitElementImpl definingCompilationUnitElement =
        builder.buildCompilationUnit(librarySource, definingCompilationUnit);
    NodeList<Directive> directives = definingCompilationUnit.getDirectives();
    LibraryIdentifier libraryNameNode = null;
    boolean hasPartDirective = false;
    FunctionElement entryPoint = findEntryPoint(definingCompilationUnitElement);
    ArrayList<Directive> directivesToResolve = new ArrayList<Directive>();
    ArrayList<CompilationUnitElementImpl> sourcedCompilationUnits =
        new ArrayList<CompilationUnitElementImpl>();
    for (Directive directive : directives) {
      //
      // We do not build the elements representing the import and export directives at this point.
      // That is not done until we get to LibraryResolver.buildDirectiveModels() because we need the
      // LibraryElements for the referenced libraries, which might not exist at this point (due to
      // the possibility of circular references).
      //
      if (directive instanceof LibraryDirective) {
        if (libraryNameNode == null) {
          libraryNameNode = ((LibraryDirective) directive).getName();
          directivesToResolve.add(directive);
        }
      } else if (directive instanceof PartDirective) {
        PartDirective partDirective = (PartDirective) directive;
        StringLiteral partUri = partDirective.getUri();
        Source partSource = partDirective.getSource();
        if (analysisContext.exists(partSource)) {
          hasPartDirective = true;
          CompilationUnit partUnit = library.getAST(partSource);
          CompilationUnitElementImpl part = builder.buildCompilationUnit(partSource, partUnit);
          part.setUriOffset(partUri.getOffset());
          part.setUriEnd(partUri.getEnd());
          part.setUri(partDirective.getUriContent());
          //
          // Validate that the part contains a part-of directive with the same name as the library.
          //
          String partLibraryName = getPartLibraryName(partSource, partUnit, directivesToResolve);
          if (partLibraryName == null) {
            errorListener.onError(
                new AnalysisError(
                    librarySource,
                    partUri.getOffset(),
                    partUri.getLength(),
                    CompileTimeErrorCode.PART_OF_NON_PART,
                    partUri.toSource()));
          } else if (libraryNameNode == null) {
            // TODO(brianwilkerson) Collect the names declared by the part. If they are all the same
            // then we can use that name as the inferred name of the library and present it in a
            // quick-fix.
            // partLibraryNames.add(partLibraryName);
          } else if (!libraryNameNode.getName().equals(partLibraryName)) {
            errorListener.onError(
                new AnalysisError(
                    librarySource,
                    partUri.getOffset(),
                    partUri.getLength(),
                    StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
                    libraryNameNode.getName(),
                    partLibraryName));
          }
          if (entryPoint == null) {
            entryPoint = findEntryPoint(part);
          }
          directive.setElement(part);
          sourcedCompilationUnits.add(part);
        }
      }
    }

    if (hasPartDirective && libraryNameNode == null) {
      errorListener.onError(
          new AnalysisError(librarySource, ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART));
    }
    //
    // Create and populate the library element.
    //
    LibraryElementImpl libraryElement =
        new LibraryElementImpl(analysisContext.getContextFor(librarySource), libraryNameNode);
    libraryElement.setDefiningCompilationUnit(definingCompilationUnitElement);
    if (entryPoint != null) {
      libraryElement.setEntryPoint(entryPoint);
    }
    int sourcedUnitCount = sourcedCompilationUnits.size();
    libraryElement.setParts(
        sourcedCompilationUnits.toArray(new CompilationUnitElementImpl[sourcedUnitCount]));
    for (Directive directive : directivesToResolve) {
      directive.setElement(libraryElement);
    }
    library.setLibraryElement(libraryElement);
    if (sourcedUnitCount > 0) {
      patchTopLevelAccessors(libraryElement);
    }
    return libraryElement;
  }