예제 #1
0
  /**
   * Method for tracking macro expansions.
   *
   * @since 5.0
   */
  public void expand(
      String beforeExpansion,
      MacroExpansionTracker tracker,
      String filePath,
      int lineNumber,
      boolean protectDefinedConstructs) {
    fImplicitMacroExpansions.clear();
    fImageLocationInfos.clear();
    fFixedInput = beforeExpansion.toCharArray();
    fFixedCurrentFilename = filePath;
    fFixedLineNumber = lineNumber;
    Lexer lexer = new Lexer(fFixedInput, fLexOptions, fLog, this);

    try {
      tracker.start(lexer);
      Token identifier = lexer.nextToken();
      if (identifier.getType() != IToken.tIDENTIFIER) {
        tracker.fail();
        return;
      }
      PreprocessorMacro macro = fDictionary.get(identifier.getCharImage());
      if (macro == null) {
        tracker.fail();
        return;
      }
      lexer.nextToken();

      fStartOffset = identifier.getOffset();
      fEndOffset = identifier.getEndOffset();
      fCompletionMode = false;
      IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden =
          new IdentityHashMap<PreprocessorMacro, PreprocessorMacro>();

      // setup input sequence
      TokenSource input = new TokenSource(lexer);
      TokenList firstExpansion = new TokenList();

      firstExpansion.append(new ExpansionBoundary(macro, true));
      expandOne(identifier, macro, forbidden, input, firstExpansion, tracker);
      firstExpansion.append(new ExpansionBoundary(macro, false));
      input.prepend(firstExpansion);

      TokenList result = expandAll(input, forbidden, protectDefinedConstructs, tracker);
      tracker.finish(result, fEndOffset);
    } catch (OffsetLimitReachedException e) {
    }
  }
예제 #2
0
  /** Expects that the identifier has been consumed, stores the result in the list provided. */
  public TokenList expand(
      ITokenSequence lexer,
      final boolean isPPCondition,
      PreprocessorMacro macro,
      Token identifier,
      boolean completionMode)
      throws OffsetLimitReachedException {
    fImplicitMacroExpansions.clear();
    fImageLocationInfos.clear();

    fStartOffset = identifier.getOffset();
    fEndOffset = identifier.getEndOffset();
    fCompletionMode = completionMode;

    IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden =
        new IdentityHashMap<PreprocessorMacro, PreprocessorMacro>();

    // setup input sequence
    TokenSource input = new TokenSource(lexer);
    TokenList firstExpansion = new TokenList();

    TokenList result;
    try {
      firstExpansion.append(new ExpansionBoundary(macro, true));
      expandOne(identifier, macro, forbidden, input, firstExpansion, null);
      firstExpansion.append(new ExpansionBoundary(macro, false));

      input.prepend(firstExpansion);

      result = expandAll(input, forbidden, isPPCondition, null);
    } catch (CompletionInMacroExpansionException e) {
      // for content assist in macro expansions, we return the list of
      // tokens of the
      // parameter at the current cursor position and hope that they make
      // sense if
      // they are inserted at the position of the expansion.
      // For a better solution one would have to perform the expansion
      // with artificial
      // parameters and then check where the completion token ends up in
      // the expansion.
      result = e.getParameterTokens().cloneTokens();
    }
    postProcessTokens(result);
    return result;
  }
예제 #3
0
  private TokenList expandAll(
      TokenSource input,
      IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
      boolean protectDefinedConstructs,
      MacroExpansionTracker tracker)
      throws OffsetLimitReachedException {
    final TokenList result = new TokenList();
    boolean protect = false;
    Token l = null;
    Token t = input.removeFirst();
    while (t != null) {
      switch (t.getType()) {
        case ObjCPreprocessor.tSCOPE_MARKER:
          ((ExpansionBoundary) t).execute(forbidden);
          break;
        case IToken.tIDENTIFIER:
          final char[] image = t.getCharImage();
          PreprocessorMacro macro = fDictionary.get(image);
          if (protect || (tracker != null && tracker.isDone())) {
            result.append(t);
          } else if (protectDefinedConstructs && Arrays.equals(image, Keywords.cDEFINED)) {
            t.setType(ObjCPreprocessor.tDEFINED);
            result.append(t);
            protect = true;
          }
          // tricky: don't mark function-style macros if you don't
          // find the left parenthesis
          else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
            result.append(t);
          } else if (forbidden.containsKey(macro)) {
            t.setType(ObjCPreprocessor.tEXPANDED_IDENTIFIER); // prevent
            // any
            // further
            // expansion
            result.append(t);
          } else {
            if (fLocationMap != null) {
              ImageLocationInfo info = null;
              if (fLexOptions.fCreateImageLocations) {
                info = createImageLocationInfo(t);
              }
              fImplicitMacroExpansions.add(
                  fLocationMap.encounterImplicitMacroExpansion(macro, info));
            }
            TokenList replacement = new TokenList();

            addSpacemarker(l, t, replacement); // start expansion
            replacement.append(new ExpansionBoundary(macro, true));
            Token last = expandOne(t, macro, forbidden, input, replacement, tracker);
            replacement.append(new ExpansionBoundary(macro, false));
            addSpacemarker(last, input.first(), replacement); // end
            // expansion

            input.prepend(replacement);
          }
          break;
        case IToken.tLPAREN:
        case ObjCPreprocessor.tNOSPACE:
        case ObjCPreprocessor.tSPACE:
          result.append(t);
          break;
        default:
          protect = false;
          result.append(t);
          break;
      }
      l = t;
      t = input.removeFirst();
    }
    return result;
  }