/** * Construct a {@code Formatter} given Java compilation unit. Parses the code; builds a {@link * JavaInput} and the corresponding {@link JavaOutput}. * * @param javaInput the input, a Java compilation unit * @param javaOutput the {@link JavaOutput} * @param maxWidth the maximum formatted width * @param errors mutable list to receive errors * @param indentationMultiplier the multiplier for the unit of indent; the default is 1 */ static void format( JavaInput javaInput, JavaOutput javaOutput, int maxWidth, List<FormatterDiagnostic> errors, int indentationMultiplier) { ASTParser parser = ASTParser.newParser(AST.JLS8); parser.setSource(javaInput.getText().toCharArray()); @SuppressWarnings("unchecked") // safe by specification Map<String, String> options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); parser.setCompilerOptions(options); CompilationUnit unit = (CompilationUnit) parser.createAST(null); javaInput.setCompilationUnit(unit); if (unit.getMessages().length > 0) { for (Message message : unit.getMessages()) { errors.add(javaInput.createDiagnostic(message.getStartPosition(), message.getMessage())); } return; } OpsBuilder builder = new OpsBuilder(javaInput, javaOutput, errors); // Output compilation unit. new JavaInputAstVisitor(builder, indentationMultiplier).visit(unit); builder.sync(javaInput.getText().length()); builder.drain(); Doc doc = new DocBuilder().withOps(builder.build()).build(); doc.computeBreaks(javaOutput.getCommentsHelper(), maxWidth, new Doc.State(+0, 0, 0)); doc.write(javaOutput); javaOutput.flush(); }
/** * Emit a list of {@link Replacement}s to convert from input to output. * * @param input the input compilation unit * @param characterRanges the character ranges to reformat * @return a list of {@link Replacement}s, sorted from low index to high index, without overlaps * @throws FormatterException if the input string cannot be parsed */ public ImmutableList<Replacement> getFormatReplacements( String input, List<Range<Integer>> characterRanges) throws FormatterException { JavaInput javaInput = new JavaInput(STDIN_FILENAME, input); JavaOutput javaOutput = new JavaOutput(javaInput, new JavaCommentsHelper()); List<FormatterDiagnostic> errors = new ArrayList<>(); format(javaInput, javaOutput, MAX_WIDTH, errors, 1); if (!errors.isEmpty()) { throw new FormatterException(errors); } RangeSet<Integer> tokenRangeSet = characterRangesToTokenRanges(javaInput, characterRanges); return javaOutput.getFormatReplacements(tokenRangeSet); }
/** * Input constructor. * * @param text the input text * @throws FormatterException if the input cannot be parsed */ public JavaInput(String filename, String text) throws FormatterException { this.filename = filename; this.text = text; char[] chars = text.toCharArray(); List<String> lines = NEWLINE_SPLITTER.splitToList(text); setLines(ImmutableList.copyOf(lines)); ImmutableList<Tok> toks = buildToks(text, chars); positionToColumnMap = makePositionToColumnMap(toks); tokens = buildTokens(toks); ImmutableSortedMap.Builder<Integer, Token> locationTokenMap = ImmutableSortedMap.naturalOrder(); for (Token token : tokens) { locationTokenMap.put(JavaOutput.startTok(token).getPosition(), token); } positionTokenMap = locationTokenMap.build(); // adjust kN for EOF kToToken = new Token[kN + 1]; for (Token token : tokens) { for (Input.Tok tok : token.getToksBefore()) { if (tok.getIndex() < 0) { continue; } kToToken[tok.getIndex()] = token; } kToToken[token.getTok().getIndex()] = token; for (Input.Tok tok : token.getToksAfter()) { if (tok.getIndex() < 0) { continue; } kToToken[tok.getIndex()] = token; } } }
/** * Format an input string (a compilation), for only the specified character ranges. These ranges * are extended as necessary (e.g., to encompass whole lines). * * @param input the input string * @param characterRanges the character ranges to be reformatted * @return the output string * @throws FormatterException if the input string cannot be parsed */ public String formatSource(String input, List<Range<Integer>> characterRanges) throws FormatterException { JavaInput javaInput = new JavaInput(STDIN_FILENAME, input); JavaOutput javaOutput = new JavaOutput(javaInput, new JavaCommentsHelper()); List<FormatterDiagnostic> errors = new ArrayList<>(); format(javaInput, javaOutput, MAX_WIDTH, errors, 1); if (!errors.isEmpty()) { throw new FormatterException(errors); } StringBuilder result = new StringBuilder(input.length()); RangeSet<Integer> tokenRangeSet = characterRangesToTokenRanges(javaInput, characterRanges); try { javaOutput.writeMerged(result, tokenRangeSet); } catch (IOException ignored) { throw new AssertionError("IOException impossible for StringWriter"); } return result.toString(); }