private boolean rangeAdded(TextEdit edit) {
   unchangedUntil(edit.getOffset());
   buf.append("<b>"); // $NON-NLS-1$
   appendContent(previewContent, edit.getOffset(), edit.getExclusiveEnd(), buf, false);
   buf.append("</b>"); // $NON-NLS-1$
   fWrittenToPos = edit.getExclusiveEnd();
   return false;
 }
예제 #2
0
  private void handleReplace(IASTNode node) {
    List<ASTModification> modifications = getModifications(node, ModificationKind.REPLACE);
    String source = node.getTranslationUnit().getRawSignature();
    TextEdit edit;
    ChangeGeneratorWriterVisitor writer =
        new ChangeGeneratorWriterVisitor(modificationStore, commentMap);
    IASTFileLocation fileLocation = node.getFileLocation();
    Integer val = sourceOffsets.get(fileLocation.getFileName());
    int processedOffset = val != null ? val.intValue() : 0;
    if (modifications.size() == 1 && modifications.get(0).getNewNode() == null) {
      int offset = getOffsetIncludingComments(node);
      int endOffset = getEndOffsetIncludingComments(node);
      offset = Math.max(skipPrecedingBlankLines(source, offset), processedOffset);
      endOffset = skipTrailingBlankLines(source, endOffset);
      IASTNode[] siblingsList = getContainingNodeList(node);
      if (siblingsList != null) {
        if (siblingsList.length > 1) {
          if (node == siblingsList[0]) {
            endOffset = skipToTrailingDelimiter(source, ',', endOffset);
          } else {
            offset = skipToPrecedingDelimiter(source, ',', offset);
          }
        } else if (node.getPropertyInParent() == ICPPASTFunctionDefinition.MEMBER_INITIALIZER) {
          offset = skipToPrecedingDelimiter(source, ':', offset);
        }
      }
      IASTNode prevNode = getPreviousSiblingOrPreprocessorNode(node);
      IASTNode nextNode = getNextSiblingOrPreprocessorNode(node);
      if (prevNode != null && nextNode != null) {
        if (ASTWriter.requireBlankLineInBetween(prevNode, nextNode)) {
          writer.newLine();
        }
      } else if (node.getParent() instanceof ICPPASTNamespaceDefinition) {
        writer.newLine();
      }
      String code = writer.toString();
      edit = new ReplaceEdit(offset, endOffset - offset, code);
    } else {
      node.accept(writer);
      String code = writer.toString();
      int offset = fileLocation.getNodeOffset();
      int endOffset = offset + fileLocation.getNodeLength();
      if (node instanceof IASTStatement || node instanceof IASTDeclaration) {
        // Include trailing comments in the area to be replaced.
        endOffset = Math.max(endOffset, getEndOffsetIncludingTrailingComments(node));
      }
      String lineSeparator = writer.getScribe().getLineSeparator();
      if (code.endsWith(lineSeparator)) {
        code = code.substring(0, code.length() - lineSeparator.length());
      }
      edit = new ReplaceEdit(offset, endOffset - offset, code);
    }
    IFile file = FileHelper.getFileFromNode(node);
    MultiTextEdit parentEdit = getEdit(node, file);
    parentEdit.addChild(edit);

    sourceOffsets.put(fileLocation.getFileName(), edit.getExclusiveEnd());
  }
  private void formatAndAssertEquals(
      String beforePath, String afterPath, XMLFormattingPreferences prefs)
      throws UnsupportedEncodingException, IOException, CoreException {
    IStructuredModel beforeModel = null, afterModel = null;
    try {
      beforeModel = getModelForEdit(beforePath);
      assertNotNull("could not retrieve structured model for : " + beforePath, beforeModel);

      afterModel = getModelForEdit(afterPath);
      assertNotNull("could not retrieve structured model for : " + afterPath, afterModel);

      IStructuredDocument document = beforeModel.getStructuredDocument();

      String normalizedContents = document.get();
      normalizedContents = StringUtils.replace(normalizedContents, "\r\n", "\n");
      normalizedContents = StringUtils.replace(normalizedContents, "\r", "\n");
      document.set(normalizedContents);

      if (prefs == null) prefs = new XMLFormattingPreferences();
      TextEdit edit = partitionFormatter.format(beforeModel, 0, document.getLength(), prefs);
      try {
        edit.apply(document);
      } catch (MalformedTreeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      ByteArrayOutputStream formattedBytes = new ByteArrayOutputStream();
      beforeModel.save(formattedBytes); // "beforeModel" should now be
      // after the formatter

      ByteArrayOutputStream afterBytes = new ByteArrayOutputStream();
      afterModel.save(afterBytes);

      String expectedContents = new String(afterBytes.toByteArray(), UTF_8);
      String actualContents = new String(formattedBytes.toByteArray(), UTF_8);

      /* Make some adjustments to ignore cross platform line delimiter issues */
      expectedContents = StringUtils.replace(expectedContents, "\r\n", "\n");
      expectedContents = StringUtils.replace(expectedContents, "\r", "\n");
      actualContents = StringUtils.replace(actualContents, "\r\n", "\n");
      actualContents = StringUtils.replace(actualContents, "\r", "\n");

      assertTrue(
          "Formatted document differs from the expected.\nExpected Contents:\n"
              + expectedContents
              + "\nActual Contents:\n"
              + actualContents,
          fStringCompareUtil.equalsIgnoreLineSeperator(expectedContents, actualContents));
    } finally {
      if (beforeModel != null) beforeModel.releaseFromEdit();
      if (afterModel != null) afterModel.releaseFromEdit();
    }
  }
예제 #4
0
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.andmore.android.model.java.JavaClass#addComments()
   */
  @Override
  protected void addComments() throws AndroidException {
    ASTNode todoComment;

    ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setSource(document.get().toCharArray());

    compUnit = (CompilationUnit) parser.createAST(null);
    ast = compUnit.getAST();
    rewrite = ASTRewrite.create(ast);

    todoComment =
        rewrite.createStringPlaceholder(
            CodeUtilsNLS.MODEL_Common_ToDoPutYourCodeHere, ASTNode.EMPTY_STATEMENT);

    TypeDeclaration receiverClass = (TypeDeclaration) compUnit.types().get(0);
    MethodDeclaration method;
    Block block;

    // Adds the Override annotation and ToDo comment to all overridden
    // methods
    for (int i = 0; i < receiverClass.bodyDeclarations().size(); i++) {
      method = (MethodDeclaration) receiverClass.bodyDeclarations().get(i);

      // Adds the Override annotation
      rewrite
          .getListRewrite(method, method.getModifiersProperty())
          .insertFirst(OVERRIDE_ANNOTATION, null);

      // Adds the ToDo comment
      block = method.getBody();
      rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertFirst(todoComment, null);
    }

    try {
      // Writes the modifications
      TextEdit modifications = rewrite.rewriteAST(document, null);
      modifications.apply(document);
    } catch (IllegalArgumentException e) {
      String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);

      AndmoreLogger.error(BroadcastReceiverClass.class, errMsg, e);
      throw new AndroidException(errMsg);
    } catch (MalformedTreeException e) {
      String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);

      AndmoreLogger.error(BroadcastReceiverClass.class, errMsg, e);
      throw new AndroidException(errMsg);
    } catch (BadLocationException e) {
      String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);

      AndmoreLogger.error(BroadcastReceiverClass.class, errMsg, e);
      throw new AndroidException(errMsg);
    }
  }
예제 #5
0
  /** Return this {@link JavaSource} file as a String */
  @Override
  public String toString() {
    Document document = new Document(this.document.get());

    try {
      TextEdit edit = unit.rewrite(document, null);
      edit.apply(document);
    } catch (Exception e) {
      throw new ParserException("Could not modify source: " + unit.toString(), e);
    }

    return Formatter.format(document.get());
  }
예제 #6
0
 /**
  * It is OK to apply more than one insert {@link Edit} with the same offset.
  *
  * <p>For example Quick Fix "Implement Missing Overrides" inserts several method declarations.
  */
 public void test_toLTK_SourceChange_twoInserts() throws Exception {
   Source source = createTestFileSource();
   // fill SourceChange
   SourceChange sourceChange = new SourceChange("My change", source);
   sourceChange.addEdit(new Edit(2, 0, "a"));
   sourceChange.addEdit(new Edit(2, 0, "b"));
   // toLTK
   TextFileChange ltkChange = ServiceUtils.toLTK(sourceChange);
   TextEdit textEdit = ltkChange.getEdit();
   // apply
   Document document = new Document("01234");
   textEdit.apply(document);
   assertEquals("01ab234", document.get());
 }
  public String format(String text, int startOffset, int endOffset, int kJavascriptUnit)
      throws FileDoesNotExistsException {
    IDocument doc = new Document();
    try {
      // format the file (the meat and potatoes)
      doc.set(text);
      /**
       * Format <code>source</code>, and returns a text edit that correspond to the difference
       * between the given string and the formatted string.
       *
       * <p>It returns null if the given string cannot be formatted.
       *
       * <p>If the offset position is matching a whitespace, the result can include whitespaces. It
       * would be up to the caller to get rid of preceeding whitespaces.
       *
       * @param kind Use to specify the kind of the code snippet to format. It can be any of these:
       *     K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_JAVASCRIPT_UNIT, K_UNKNOWN,
       *     K_SINGLE_LINE_COMMENT, K_MULTI_LINE_COMMENT, K_JAVA_DOC
       * @param source the source to format
       * @param offset the given offset to start recording the edits (inclusive).
       * @param length the given length to stop recording the edits (exclusive).
       * @param indentationLevel the initial indentation level, used to shift left/right the entire
       *     source fragment. An initial indentation level of zero or below has no effect.
       * @param lineSeparator the line separator to use in formatted source, if set to <code>null
       *     </code>, then the platform default one will be used.
       * @return the text edit
       * @throws IllegalArgumentException if offset is lower than 0, length is lower than 0 or
       *     length is greater than source length.
       */
      TextEdit edit =
          getCodeFormatter()
              .format(
                  kJavascriptUnit,
                  text,
                  startOffset,
                  endOffset - startOffset,
                  0,
                  Settings.LINE_SEPARATOR);
      if (edit != null) {
        edit.apply(doc);
      } else {
        throw new FormattingFailedException();
      }

      return doc.get();
    } catch (BadLocationException e) {
      throw new RuntimeException(e);
    }
  }
예제 #8
0
 public String format(final String input) throws BadLocationException {
   final IDocument doc = new Document();
   doc.set(input);
   final TextEdit edit =
       formatter.format(
           CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS,
           input,
           0,
           input.length(),
           0,
           "\n");
   if (edit == null) throw new RuntimeException("formatting failed");
   edit.apply(doc);
   return doc.get();
 }
예제 #9
0
  public String format(String source) {
    TextEdit edit = codeFormatter.format(0, source, 0, source.length(), 0, null);

    IDocument document = new Document(source);
    String formattedSource;

    try {
      edit.apply(document);
      formattedSource = document.get();
    } catch (MalformedTreeException e) {
      formattedSource = source;
    } catch (BadLocationException e) {
      formattedSource = source;
    }
    return formattedSource;
  }
예제 #10
0
 protected void applyTextEdit(CompilationUnit cu, TextEdit edits) throws DartModelException {
   try {
     edits.apply(getDocument(cu));
   } catch (BadLocationException e) {
     // content changed under us
     throw new DartModelException(e, DartModelStatusConstants.INVALID_CONTENTS);
   }
 }
예제 #11
0
  @Test
  public void testName() throws Exception {
    HashMap<String, String> javaFormattingPrefs = TestUtils.getJavaProperties();

    int i = INPUT.indexOf("/*-");
    int i2 = INPUT.indexOf("-*/");
    TypedPosition partition = new TypedPosition(i, i2 - i + 3, "");
    HashMap<String, String> jsMap = TestUtils.getJSProperties();

    IDocument document = new Document(INPUT);
    TextEdit format1 =
        JsniFormattingUtil.format(document, partition, javaFormattingPrefs, jsMap, null);
    // TextEdit format1 = JsniFormattingUtil.format(document,javaFormattingPrefs, jsMap, null);
    format1.apply(document);
    Assert.assertEquals(FORMATTED, document.get());
    System.err.println(FORMATTED);
  }
예제 #12
0
 /**
  * Formats the specified compilation unit.
  *
  * @param unit the compilation unit to format
  * @param monitor the monitor for the operation
  * @throws JavaModelException
  */
 public static void formatUnitSourceCode(ICompilationUnit unit, IProgressMonitor monitor)
     throws JavaModelException {
   CodeFormatter formatter = ToolFactory.createCodeFormatter(null);
   ISourceRange range = unit.getSourceRange();
   TextEdit formatEdit =
       formatter.format(
           CodeFormatter.K_COMPILATION_UNIT,
           unit.getSource(),
           range.getOffset(),
           range.getLength(),
           0,
           null);
   if (formatEdit != null && formatEdit.hasChildren()) {
     unit.applyTextEdit(formatEdit, monitor);
   } else {
     monitor.done();
   }
 }
예제 #13
0
  public void run(IStructuredSelection selection) {
    final ModuleCollector collector = new ModuleCollector();

    // Add by Oliver. Fill the source model into collector.modules.
    initSelectedVjoType(selection, collector);

    if (!collector.modules.isEmpty()) {
      for (Iterator i = collector.modules.iterator(); i.hasNext(); ) {
        final ISourceModule module = (ISourceModule) i.next();
        final IResource resource = module.getResource();
        if (resource != null && resource.getType() == IResource.FILE && resource.exists()) {
          final IScriptProject project = module.getScriptProject();
          final IScriptFormatterFactory formatterFactory =
              ScriptFormatterManager.getSelected(project);
          if (formatterFactory != null) {
            try {
              final String source = module.getSource();
              final Document document = new Document(source);
              final String lineDelimiter = TextUtilities.getDefaultLineDelimiter(document);
              final Map preferences =
                  formatterFactory.retrievePreferences(new PreferencesLookupDelegate(project));
              final IScriptFormatter formatter =
                  formatterFactory.createFormatter(lineDelimiter, preferences);
              final TextEdit edit = formatter.format(source, 0, source.length(), 0);
              if (edit != null) {
                edit.apply(document);
                final String newSource = document.get();
                if (!source.equals(newSource)) {
                  module.becomeWorkingCopy(null, null);
                  module.getBuffer().setContents(newSource);
                  module.commitWorkingCopy(true, null);
                }
              }
            } catch (Exception e) {
              DLTKUIPlugin.log(e);
              break;
            }
          }
        }
      }
    }
  }
예제 #14
0
 @Override
 public int getStartPosition() {
   if (this.group.isEmpty()) {
     return this.node.getOffset();
   }
   IRegion coverage = TextEdit.getCoverage(this.group.getTextEdits());
   if (coverage == null) {
     return this.node.getOffset();
   }
   return coverage.getOffset();
 }
예제 #15
0
 @Override
 public int getLength() {
   if (this.group.isEmpty()) {
     return this.node.getLength();
   }
   IRegion coverage = TextEdit.getCoverage(this.group.getTextEdits());
   if (coverage == null) {
     return this.node.getLength();
   }
   return coverage.getLength();
 }
    @Override
    protected void addEdits(IDocument document, TextEdit rootEdit) throws CoreException {
      try {
        String lineDelimiter = TextUtilities.getDefaultLineDelimiter(document);
        final IJavaProject project = getCompilationUnit().getJavaProject();
        IRegion region = document.getLineInformationOfOffset(fInsertPosition);

        String lineContent = document.get(region.getOffset(), region.getLength());
        String indentString = Strings.getIndentString(lineContent, project);
        String str = Strings.changeIndent(fComment, 0, project, indentString, lineDelimiter);
        InsertEdit edit = new InsertEdit(fInsertPosition, str);
        rootEdit.addChild(edit);
        if (fComment.charAt(fComment.length() - 1) != '\n') {
          rootEdit.addChild(new InsertEdit(fInsertPosition, lineDelimiter));
          rootEdit.addChild(new InsertEdit(fInsertPosition, indentString));
        }
      } catch (BadLocationException e) {
        throw new CoreException(JavaUIStatus.createError(IStatus.ERROR, e));
      }
    }
예제 #17
0
  @Override
  protected void doFormatPreview() {
    if (fSnippets.isEmpty()) {
      fPreviewDocument.set(""); // $NON-NLS-1$
      return;
    }

    // This delimiter looks best for invisible characters
    final String delimiter = "\n"; // $NON-NLS-1$

    final StringBuilder buffer = new StringBuilder();
    for (PreviewSnippet snippet : fSnippets) {
      String formattedSource;
      try {
        TextEdit edit =
            CodeFormatterUtil.format(snippet.kind, snippet.source, 0, delimiter, fWorkingValues);
        if (edit == null) {
          formattedSource = snippet.source;
        } else {
          Document document = new Document(snippet.source);
          edit.apply(document, TextEdit.NONE);
          formattedSource = document.get();
        }
      } catch (Exception e) {
        final IStatus status =
            new Status(
                IStatus.ERROR,
                CUIPlugin.getPluginId(),
                ICStatusConstants.INTERNAL_ERROR,
                FormatterMessages.CPreview_formatter_exception,
                e);
        CUIPlugin.log(status);
        continue;
      }
      buffer.append(delimiter);
      buffer.append(formattedSource);
      buffer.append(delimiter);
      buffer.append(delimiter);
    }
    fPreviewDocument.set(buffer.toString());
  }
 /**
  * 格式化源码
  *
  * @param code
  * @return
  */
 @SuppressWarnings({"rawtypes", "unchecked"})
 private static String formatBodyCode(String code) {
   try {
     // 此处可以修改格式化配置
     Map m = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
     m.put(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT, "100");
     m.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS, "true");
     m.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
     CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(m);
     TextEdit textEdit =
         codeFormatter.format(CodeFormatter.K_UNKNOWN, code, 0, code.length(), 0, null);
     if (textEdit != null) {
       IDocument doc = new Document(code);
       textEdit.apply(doc);
       return doc.get();
     }
   } catch (BadLocationException e) {
     LOG.error("格式化源代码失败", e);
   }
   return code;
 }
예제 #19
0
  private static IRegion getCorrespondingEditChangeRange(
      SearchMatch searchResult, TextChangeManager manager) {
    TextChange change = getTextChange(searchResult, manager);
    if (change == null) return null;

    IRegion oldMatchRange = createTextRange(searchResult);
    TextEditChangeGroup[] editChanges = change.getTextEditChangeGroups();
    for (int i = 0; i < editChanges.length; i++) {
      if (oldMatchRange.equals(editChanges[i].getRegion()))
        return TextEdit.getCoverage(change.getPreviewEdits(editChanges[i].getTextEdits()));
    }
    return null;
  }
 /**
  * Adds the specified tag to the source member defined by the member name and signature
  *
  * @param unit
  * @param membername
  * @param signature
  * @param tagname
  * @param remove
  * @throws CoreException
  * @throws MalformedTreeException
  * @throws BadLocationException
  */
 private void updateTagInSource(
     ICompilationUnit unit, String membername, String signature, String tagname, boolean remove)
     throws CoreException, MalformedTreeException, BadLocationException {
   ASTParser parser = ASTParser.newParser(AST.JLS4);
   parser.setSource(unit);
   CompilationUnit cunit = (CompilationUnit) parser.createAST(new NullProgressMonitor());
   assertNotNull("the ast compilation unit cannot be null", cunit);
   cunit.recordModifications();
   ASTRewrite rewrite = ASTRewrite.create(cunit.getAST());
   cunit.accept(new SourceChangeVisitor(membername, signature, tagname, remove, rewrite));
   ITextFileBufferManager bm = FileBuffers.getTextFileBufferManager();
   IPath path = cunit.getJavaElement().getPath();
   try {
     bm.connect(path, LocationKind.IFILE, null);
     ITextFileBuffer tfb = bm.getTextFileBuffer(path, LocationKind.IFILE);
     IDocument document = tfb.getDocument();
     TextEdit edits = rewrite.rewriteAST(document, null);
     edits.apply(document);
     tfb.commit(new NullProgressMonitor(), true);
   } finally {
     bm.disconnect(path, LocationKind.IFILE, null);
   }
 }
예제 #21
0
  /**
   * @param change
   * @return Map &lt;Integer oldOffset, Integer updatedOffset&gt;
   */
  private static Map<Integer, Integer> getEditChangeOffsetUpdates(TextChange change) {
    TextEditChangeGroup[] editChanges = change.getTextEditChangeGroups();
    Map<Integer, Integer> offsetUpdates = new HashMap<>(editChanges.length);
    for (int i = 0; i < editChanges.length; i++) {
      TextEditChangeGroup editChange = editChanges[i];
      IRegion oldRegion = editChange.getRegion();
      if (oldRegion == null) continue;
      IRegion updatedRegion =
          TextEdit.getCoverage(change.getPreviewEdits(editChange.getTextEdits()));
      if (updatedRegion == null) continue;

      offsetUpdates.put(new Integer(oldRegion.getOffset()), new Integer(updatedRegion.getOffset()));
    }
    return offsetUpdates;
  }
예제 #22
0
  public void testASTRewriteExample() throws Exception {
    // create a new project
    IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("Test");
    project.create(null);
    project.open(null);
    try {
      // set the Java nature and Java build path
      IProjectDescription description = project.getDescription();
      description.setNatureIds(new String[] {JavaCore.NATURE_ID});
      project.setDescription(description, null);

      IJavaProject javaProject = JavaCore.create(project);

      // build path is: project as source folder and JRE container
      IClasspathEntry[] cpentry =
          new IClasspathEntry[] {
            JavaCore.newSourceEntry(javaProject.getPath()),
            JavaRuntime.getDefaultJREContainerEntry()
          };
      javaProject.setRawClasspath(cpentry, javaProject.getPath(), null);
      Map<String, String> options = new HashMap<>();
      options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
      options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4");
      javaProject.setOptions(options);

      // create a test file
      IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(project);
      IPackageFragment pack1 = root.createPackageFragment("test1", false, null);
      StringBuffer buf = new StringBuffer();
      buf.append("package test1;\n");
      buf.append("public class E {\n");
      buf.append("    public void foo(int i) {\n");
      buf.append("        while (--i > 0) {\n");
      buf.append("            System.beep();\n");
      buf.append("        }\n");
      buf.append("    }\n");
      buf.append("}\n");
      ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null);

      // create an AST
      ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
      parser.setSource(cu);
      parser.setResolveBindings(false);
      CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
      AST ast = astRoot.getAST();

      // create the descriptive ast rewriter
      ASTRewrite rewrite = ASTRewrite.create(ast);

      // get the block node that contains the statements in the method body
      TypeDeclaration typeDecl = (TypeDeclaration) astRoot.types().get(0);
      MethodDeclaration methodDecl = typeDecl.getMethods()[0];
      Block block = methodDecl.getBody();

      // create new statements to insert
      MethodInvocation newInv1 = ast.newMethodInvocation();
      newInv1.setName(ast.newSimpleName("bar1"));
      Statement newStatement1 = ast.newExpressionStatement(newInv1);

      MethodInvocation newInv2 = ast.newMethodInvocation();
      newInv2.setName(ast.newSimpleName("bar2"));
      Statement newStatement2 = ast.newExpressionStatement(newInv2);

      // describe that the first node is inserted as first statement in block, the other one as last
      // statement
      // note: AST is not modified by this
      ListRewrite listRewrite = rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY);
      listRewrite.insertFirst(newStatement1, null);
      listRewrite.insertLast(newStatement2, null);

      // evaluate the text edits corresponding to the described changes. AST and CU still
      // unmodified.
      TextEdit res = rewrite.rewriteAST();

      // apply the text edits to the compilation unit
      Document document = new Document(cu.getSource());
      res.apply(document);
      cu.getBuffer().setContents(document.get());

      // test result
      String preview = cu.getSource();

      buf = new StringBuffer();
      buf.append("package test1;\n");
      buf.append("public class E {\n");
      buf.append("    public void foo(int i) {\n");
      buf.append("        bar1();\n");
      buf.append("        while (--i > 0) {\n");
      buf.append("            System.beep();\n");
      buf.append("        }\n");
      buf.append("        bar2();\n");
      buf.append("    }\n");
      buf.append("}\n");
      assertEquals(preview, buf.toString());
    } finally {
      project.delete(true, null);
    }
  }
예제 #23
0
  /**
   * Applies the C++ code formatter to the code affected by refactoring.
   *
   * @param multiEdit The text edit produced by refactoring.
   * @param code The code being modified.
   * @param project The project containing the code.
   * @return The text edit containing formatted refactoring changes, or the original text edit in
   *     case of errors.
   */
  private MultiTextEdit formatChangedCode(MultiTextEdit multiEdit, String code, IProject project) {
    IDocument document = new Document(code);
    try {
      // Apply refactoring changes to a temporary document.
      TextEdit edit = multiEdit.copy();
      edit.apply(document, TextEdit.UPDATE_REGIONS);

      // Expand regions affected by the changes to cover complete lines. We calculate two
      // sets of regions, reflecting the state of the document before and after
      // the refactoring changes.
      TextEdit[] edits = edit.getChildren();
      TextEdit[] originalEdits = multiEdit.getChildren();
      IRegion[] regionsAfter = new IRegion[edits.length];
      IRegion[] regionsBefore = new IRegion[edits.length];
      int numRegions = 0;
      int prevEnd = -1;
      for (int i = 0; i < edits.length; i++) {
        edit = edits[i];
        int offset = edit.getOffset();
        int end = offset + edit.getLength();
        int newOffset = document.getLineInformationOfOffset(offset).getOffset();
        int newEnd = endOffset(document.getLineInformationOfOffset(end));
        edit = originalEdits[i];
        int offsetBefore = edit.getOffset();
        int newOffsetBefore = newOffset + offsetBefore - offset;
        int newEndBefore = newEnd + offsetBefore + edit.getLength() - end;
        if (newOffset <= prevEnd) {
          numRegions--;
          newOffset = regionsAfter[numRegions].getOffset();
          newOffsetBefore = regionsBefore[numRegions].getOffset();
        }
        prevEnd = newEnd;
        regionsAfter[numRegions] = new Region(newOffset, newEnd - newOffset);
        regionsBefore[numRegions] = new Region(newOffsetBefore, newEndBefore - newOffsetBefore);
        numRegions++;
      }

      if (numRegions < regionsAfter.length) {
        regionsAfter = Arrays.copyOf(regionsAfter, numRegions);
        regionsBefore = Arrays.copyOf(regionsBefore, numRegions);
      }

      // Calculate formatting changes for the regions after the refactoring changes.
      ICProject proj = CCorePlugin.getDefault().getCoreModel().create(project);
      Map<String, String> options = proj.getOptions(true);
      // Allow all comments to be indented.
      options.put(
          DefaultCodeFormatterConstants
              .FORMATTER_COMMENT_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN,
          DefaultCodeFormatterConstants.FALSE);
      CodeFormatter formatter = ToolFactory.createCodeFormatter(options);
      code = document.get();
      TextEdit[] formatEdits =
          formatter.format(
              CodeFormatter.K_TRANSLATION_UNIT,
              code,
              regionsAfter,
              TextUtilities.getDefaultLineDelimiter(document));

      // For each of the regions we apply formatting changes and create a ReplaceEdit using
      // the region before the refactoring changes and the text after the formatting changes.
      MultiTextEdit resultEdit = new MultiTextEdit();
      for (int i = 0; i < regionsAfter.length; i++) {
        IRegion region = regionsAfter[i];
        int offset = region.getOffset();
        edit = formatEdits[i];
        edit.moveTree(-offset);
        document = new Document(code.substring(offset, offset + region.getLength()));
        edit.apply(document, TextEdit.NONE);
        region = regionsBefore[i];
        edit = new ReplaceEdit(region.getOffset(), region.getLength(), document.get());
        resultEdit.addChild(edit);
      }
      return resultEdit;
    } catch (MalformedTreeException e) {
      CCorePlugin.log(e);
      return multiEdit;
    } catch (BadLocationException e) {
      CCorePlugin.log(e);
      return multiEdit;
    }
  }
 private boolean rangeRemoved(TextEdit edit) {
   unchangedUntil(edit.getOffset());
   return false;
 }
  @Override
  public String getAdditionalProposalInfo() {
    final StringBuilder buf = new StringBuilder();

    try {
      final TextChange change = getTextChange();

      change.setKeepPreviewEdits(true);
      final IDocument previewContent = change.getPreviewDocument(new NullProgressMonitor());
      final TextEdit rootEdit = change.getPreviewEdit(change.getEdit());

      class EditAnnotator extends TextEditVisitor {
        private int fWrittenToPos = 0;

        public void unchangedUntil(int pos) {
          if (pos > fWrittenToPos) {
            appendContent(previewContent, fWrittenToPos, pos, buf, true);
            fWrittenToPos = pos;
          }
        }

        @Override
        public boolean visit(MoveTargetEdit edit) {
          return true; // rangeAdded(edit);
        }

        @Override
        public boolean visit(CopyTargetEdit edit) {
          return true; // return rangeAdded(edit);
        }

        @Override
        public boolean visit(InsertEdit edit) {
          return rangeAdded(edit);
        }

        @Override
        public boolean visit(ReplaceEdit edit) {
          if (edit.getLength() > 0) return rangeAdded(edit);
          return rangeRemoved(edit);
        }

        @Override
        public boolean visit(MoveSourceEdit edit) {
          return rangeRemoved(edit);
        }

        @Override
        public boolean visit(DeleteEdit edit) {
          return rangeRemoved(edit);
        }

        private boolean rangeRemoved(TextEdit edit) {
          unchangedUntil(edit.getOffset());
          return false;
        }

        private boolean rangeAdded(TextEdit edit) {
          unchangedUntil(edit.getOffset());
          buf.append("<b>"); // $NON-NLS-1$
          appendContent(previewContent, edit.getOffset(), edit.getExclusiveEnd(), buf, false);
          buf.append("</b>"); // $NON-NLS-1$
          fWrittenToPos = edit.getExclusiveEnd();
          return false;
        }
      }
      EditAnnotator ea = new EditAnnotator();
      rootEdit.accept(ea);

      // Final pre-existing region
      ea.unchangedUntil(previewContent.getLength());
    } catch (CoreException e) {
      CUIPlugin.log(e);
    }
    return buf.toString();
  }