public EclipseCCodeFormatter() { HashMap<String, String> options = CCorePlugin.getOptions(); codeFormatter = org.eclipse.cdt.core.ToolFactory.createDefaultCodeFormatter(options); }
/** * 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; } }