protected void consumeSingleTypeImportDeclarationName() {
    // SingleTypeImportDeclarationName ::= 'import' Name
    /* push an ImportRef build from the last name
    stored in the identifier stack. */

    ImportReference impt;
    int length;
    char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
    this.identifierPtr -= length;
    long[] positions = new long[length];
    System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
    System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
    pushOnAstStack(
        impt = newImportReference(tokens, positions, false, ClassFileConstants.AccDefault));

    if (this.currentToken == TokenNameSEMICOLON) {
      impt.declarationSourceEnd = this.scanner.currentPosition - 1;
    } else {
      impt.declarationSourceEnd = impt.sourceEnd;
    }
    impt.declarationEnd = impt.declarationSourceEnd;
    // this.endPosition is just before the ;
    impt.declarationSourceStart = this.intStack[this.intPtr--];

    // recovery
    if (this.currentElement != null) {
      this.lastCheckPoint = impt.declarationSourceEnd + 1;
      this.currentElement = this.currentElement.add(impt, 0);
      this.lastIgnoredToken = -1;
      this.restartRecovery = true; // used to avoid branching back into the regular automaton
    }
    if (this.reportReferenceInfo) {
      this.requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
    }
  }
  private ImportReference copyImportReference(ImportReference importReference) {
    if (importReference == null) {
      return null;
    }

    char[][] tokensCopy = AstUtil.copyTwoDimensionalCharArray(importReference.tokens);

    ImportReference importReferenceCopy =
        new ImportReference(
            tokensCopy, importReference.sourcePositions.clone(), false, importReference.modifiers);
    importReferenceCopy.bits = importReference.bits;

    return importReferenceCopy;
  }
  protected void consumeSingleStaticImportDeclarationName() {
    // SingleTypeImportDeclarationName ::= 'import' 'static' Name
    ImportReference impt;
    int length;
    char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
    this.identifierPtr -= length;
    long[] positions = new long[length];
    System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
    System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
    pushOnAstStack(
        impt = newImportReference(tokens, positions, false, ClassFileConstants.AccStatic));

    this.modifiers = ClassFileConstants.AccDefault;
    this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)

    if (this.currentToken == TokenNameSEMICOLON) {
      impt.declarationSourceEnd = this.scanner.currentPosition - 1;
    } else {
      impt.declarationSourceEnd = impt.sourceEnd;
    }
    impt.declarationEnd = impt.declarationSourceEnd;
    // this.endPosition is just before the ;
    impt.declarationSourceStart = this.intStack[this.intPtr--];

    if (!this.statementRecoveryActivated
        && this.options.sourceLevel < ClassFileConstants.JDK1_5
        && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
      impt.modifiers =
          ClassFileConstants
              .AccDefault; // convert the static import reference to a non-static importe reference
      problemReporter().invalidUsageOfStaticImports(impt);
    }

    // recovery
    if (this.currentElement != null) {
      this.lastCheckPoint = impt.declarationSourceEnd + 1;
      this.currentElement = this.currentElement.add(impt, 0);
      this.lastIgnoredToken = -1;
      this.restartRecovery = true; // used to avoid branching back into the regular automaton
    }
    if (this.reportReferenceInfo) {
      // Name for static import is TypeName '.' Identifier
      // => accept unknown ref on identifier
      int tokensLength = impt.tokens.length - 1;
      int start = (int) (impt.sourcePositions[tokensLength] >>> 32);
      char[] last = impt.tokens[tokensLength];
      // accept all possible kind for last name, index users will have to select the right one...
      // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=86901
      this.requestor.acceptFieldReference(last, start);
      this.requestor.acceptMethodReference(last, 0, start);
      this.requestor.acceptTypeReference(last, start);
      // accept type name
      if (tokensLength > 0) {
        char[][] compoundName = new char[tokensLength][];
        System.arraycopy(impt.tokens, 0, compoundName, 0, tokensLength);
        int end = (int) impt.sourcePositions[tokensLength - 1];
        this.requestor.acceptTypeReference(compoundName, impt.sourceStart, end);
      }
    }
  }
 public int match(ASTNode node, MatchingNodeSet nodeSet) {
   int declarationsLevel = IMPOSSIBLE_MATCH;
   if (this.pattern.findReferences) {
     if (node instanceof ImportReference) {
       // With static import, we can have static method reference in import reference
       ImportReference importRef = (ImportReference) node;
       int length = importRef.tokens.length - 1;
       if (importRef.isStatic()
           && ((importRef.bits & ASTNode.OnDemand) == 0)
           && matchesName(this.pattern.selector, importRef.tokens[length])) {
         char[][] compoundName = new char[length][];
         System.arraycopy(importRef.tokens, 0, compoundName, 0, length);
         char[] declaringType =
             CharOperation.concat(
                 this.pattern.declaringQualification, this.pattern.declaringSimpleName, '.');
         if (matchesName(declaringType, CharOperation.concatWith(compoundName, '.'))) {
           declarationsLevel = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
         }
       }
     }
   }
   return nodeSet.addMatch(node, declarationsLevel);
 }
  protected void consumeStaticImportOnDemandDeclarationName() {
    // TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
    /* push an ImportRef build from the last name
    stored in the identifier stack. */

    ImportReference impt;
    int length;
    char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
    this.identifierPtr -= length;
    long[] positions = new long[length];
    System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
    System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
    pushOnAstStack(
        impt = new ImportReference(tokens, positions, true, ClassFileConstants.AccStatic));

    // star end position
    impt.trailingStarPosition = this.intStack[this.intPtr--];
    this.modifiers = ClassFileConstants.AccDefault;
    this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)

    if (this.currentToken == TokenNameSEMICOLON) {
      impt.declarationSourceEnd = this.scanner.currentPosition - 1;
    } else {
      impt.declarationSourceEnd = impt.sourceEnd;
    }
    impt.declarationEnd = impt.declarationSourceEnd;
    // this.endPosition is just before the ;
    impt.declarationSourceStart = this.intStack[this.intPtr--];

    if (!this.statementRecoveryActivated
        && this.options.sourceLevel < ClassFileConstants.JDK1_5
        && this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
      impt.modifiers =
          ClassFileConstants
              .AccDefault; // convert the static import reference to a non-static importe reference
      problemReporter().invalidUsageOfStaticImports(impt);
    }

    // recovery
    if (this.currentElement != null) {
      this.lastCheckPoint = impt.declarationSourceEnd + 1;
      this.currentElement = this.currentElement.add(impt, 0);
      this.lastIgnoredToken = -1;
      this.restartRecovery = true; // used to avoid branching back into the regular automaton
    }
    if (this.reportReferenceInfo) {
      this.requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
    }
  }
 /* (non-Javadoc)
  * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
  * Accept to report match of static field on static import
  */
 protected void matchLevelAndReportImportRef(
     ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
   if (importRef.isStatic() && binding instanceof MethodBinding) {
     super.matchLevelAndReportImportRef(importRef, binding, locator);
   }
 }
Example #7
0
    private void resolveClassReference(JsniRef jsniRef) {
      // Precedence rules as of JLS 6.4.1.
      // 1. Enclosing type.
      // 2. Visible type in same compilation unit.
      // 3. Named import.
      // 4. Same package.
      // 5. Import on demand.

      String originalName = jsniRef.className();
      String importedClassName = originalName;
      if (importedClassName.contains(".")) {
        // Only retain up the first dot to support innerclasses. E.g. import c.g.A and reference
        // @A.I::f.
        importedClassName = importedClassName.substring(0, importedClassName.indexOf("."));
      }

      // 1 & 2. Check to see if this name refers to the enclosing class or is directly accessible
      // from it.
      ReferenceBinding declaringClass = method.binding.declaringClass;
      while (declaringClass != null) {
        String declaringClassName = JdtUtil.getSourceName(declaringClass);
        if (declaringClassName.equals(importedClassName)
            || declaringClassName.endsWith("." + importedClassName)) {
          // Referring to declaring class name using unqualified name.
          jsniRef.setResolvedClassName(
              declaringClassName + originalName.substring(importedClassName.length()));
          return;
        }
        String fullClassName =
            JdtUtil.getBinaryName(declaringClass) + "$" + originalName.replace('.', '$');
        if (typeResolver.resolveType(fullClassName) != null) {
          jsniRef.setResolvedClassName(JdtUtil.getSourceName(declaringClass) + "." + originalName);
          return;
        }
        declaringClass = declaringClass.enclosingTypeAt(1);
      }

      // 3. Check to see if this name is one of the named imports.
      for (ImportReference importReference : cudImports) {
        String nameFromImport = JdtUtil.asDottedString(importReference.getImportName());
        if (!importReference.isStatic()
            && importReference.trailingStarPosition == 0
            && nameFromImport.endsWith("." + importedClassName)) {
          jsniRef.setResolvedClassName(
              nameFromImport + originalName.substring(importedClassName.length()));
          return;
        }
      }

      // 4. Check to see if this name is resolvable from the current package.
      String currentPackageBinaryClassName =
          JdtUtil.getBinaryName(
              CharOperation.charToString(method.binding.declaringClass.qualifiedPackageName()),
              originalName);

      if (typeResolver.resolveType(currentPackageBinaryClassName) != null) {
        jsniRef.setResolvedClassName(
            JdtUtil.getSourceName(
                CharOperation.charToString(method.binding.declaringClass.qualifiedPackageName()),
                originalName));
        return;
      }

      // 5. Check to see if this name is resolvable as an import on demand.
      List<String> importPackages = Lists.newArrayList("java.lang");
      for (ImportReference importReference : cudImports) {
        if (importReference.isStatic() || importReference.trailingStarPosition == 0) {
          continue;
        }
        importPackages.add(JdtUtil.asDottedString(importReference.getImportName()));
      }
      for (String importPackage : importPackages) {
        String fullClassName = importPackage + "." + originalName.replace('.', '$');
        if (typeResolver.resolveType(fullClassName) != null) {
          jsniRef.setResolvedClassName(importPackage + "." + originalName);
          return;
        }
      }

      // Otherwise leave it as it is.
      // TODO(rluble): Maybe we should leave it null here.
      jsniRef.setResolvedClassName(jsniRef.className());
    }