/** * Extracts the long literal corresponding to a given {@link LiteralTree} node from the source * code as a string. Returns null if the source code is not available. */ private static String getLongLiteral(LiteralTree literalTree, VisitorState state) { JCLiteral longLiteral = (JCLiteral) literalTree; CharSequence sourceFile = state.getSourceCode(); if (sourceFile == null) { return null; } int start = longLiteral.getStartPosition(); java.util.regex.Matcher matcher = LONG_LITERAL_PATTERN.matcher(sourceFile.subSequence(start, sourceFile.length())); if (matcher.lookingAt()) { return matcher.group(); } return null; }
/** * Gets the original source code that represents the given node. * * <p>Note that this may be different from what is returned by calling .toString() on the node. * This returns exactly what is in the source code, whereas .toString() pretty-prints the node * from its AST representation. * * @return the source code that represents the node. */ @Nullable public String getSourceForNode(Tree tree) { JCTree node = (JCTree) tree; int start = node.getStartPosition(); int end = getEndPosition(node); if (end < 0) { return null; } return getSourceCode().subSequence(start, end).toString(); }
/** Returns the comments between the "default:" case and the first statement within it, if any. */ private String comments( VisitorState state, CaseTree defaultCase, List<? extends StatementTree> defaultStatements) { // If there are no statements, then there can be no comments that we strip, // because comments are attached to the statements, not the "default:" case. if (defaultStatements.isEmpty()) { return ""; } // To extract the comments, we have to get the source code from // "default:" to the first statement, and then strip off "default:", because // we have no way of identifying the end position of just the "default:" statement. int defaultStart = ((JCTree) defaultCase).getStartPosition(); int statementStart = ((JCTree) defaultStatements.get(0)).getStartPosition(); String defaultAndComments = state.getSourceCode().subSequence(defaultStart, statementStart).toString(); String comments = defaultAndComments .substring(defaultAndComments.indexOf("default:") + "default:".length()) .trim(); if (!comments.isEmpty()) { comments = "\n" + comments + "\n"; } return comments; } }
@Override public Void visitEndElement(EndElementTree endTree, Void unused) { if (PRE_TAGS.contains(endTree.getName().toString())) { if (!containsAnotherTag) { Integer startPos = startPosStack.pollLast(); if (startPos != null) { int endPos = getStartPosition(endTree, state); String source = state.getSourceCode().subSequence(startPos, endPos).toString(); if (CONTAINS_HTML.matcher(source).find()) { dontEmitCodeFix.add(Range.closed(startPos, endPos)); } else { preTags.add(Range.closed(startPos, endPos)); } } } containsAnotherTag = true; return super.visitEndElement(endTree, null); } return super.visitEndElement(endTree, null); }
private static String removeJavadoc( VisitorState state, int startPos, Comment danglingJavadoc, SuggestedFix.Builder builder) { int javadocStart = startPos + danglingJavadoc.getSourcePos(0); int javadocEnd = javadocStart + danglingJavadoc.getText().length(); // Capturing an extra newline helps the formatter. if (state.getSourceCode().charAt(javadocEnd) == '\n') { javadocEnd++; } builder.replace(javadocStart, javadocEnd, ""); return danglingJavadoc.getText(); }
private static String getMessageOrFormat(MethodInvocationTree tree, VisitorState state) { if (tree.getArguments().size() > 1) { return "String.format(" + state .getSourceCode() .subSequence( ((JCTree) tree.getArguments().get(0)).getStartPosition(), state.getEndPosition(Iterables.getLast(tree.getArguments()))) + ")"; } return state.getSourceForNode(getOnlyElement(tree.getArguments())); }
private void handleArguments( Tree tree, List<? extends ExpressionTree> arguments, VisitorState state) { if (arguments.size() < 2 && areSingleArgumentsSelfDocumenting(tree)) { // single-argument methods are often self-documenting return; } if (arguments.stream().noneMatch(BooleanParameter::isBooleanLiteral)) { return; } MethodSymbol sym = (MethodSymbol) ASTHelpers.getSymbol(tree); if (NamedParameterComment.containsSyntheticParameterName(sym)) { return; } int start = ((JCTree) tree).getStartPosition(); int end = state.getEndPosition(getLast(arguments)); String source = state.getSourceCode().subSequence(start, end).toString(); Deque<ErrorProneToken> tokens = new ArrayDeque<>(ErrorProneTokens.getTokens(source, state.context)); forEachPair( sym.getParameters().stream(), arguments.stream(), (p, c) -> checkParameter(p, c, start, tokens, state)); }
private Description checkArrayDimensions(Tree tree, Tree type, VisitorState state) { if (!(type instanceof ArrayTypeTree)) { return NO_MATCH; } CharSequence source = state.getSourceCode(); for (; type instanceof ArrayTypeTree; type = ((ArrayTypeTree) type).getType()) { Tree elemType = ((ArrayTypeTree) type).getType(); int start = state.getEndPosition(elemType); int end = state.getEndPosition(type); if (start >= end) { continue; } String dim = source.subSequence(start, end).toString(); if (dim.isEmpty()) { continue; } ImmutableList<ErrorProneToken> tokens = ErrorProneTokens.getTokens(dim.trim(), state.context); if (tokens.size() > 2 && tokens.get(0).kind() == TokenKind.IDENTIFIER) { int nonWhitespace = CharMatcher.isNot(' ').indexIn(dim); int idx = dim.indexOf("[]", nonWhitespace); if (idx > nonWhitespace) { String replacement = dim.substring(idx) + dim.substring(0, idx); return describeMatch(tree, SuggestedFix.replace(start, end, replacement)); } } } return NO_MATCH; } }
String source = state.getSourceCode().subSequence(start, end).toString(); if (!source.contains("/*")) {
int end = state.getEndPosition(getLast(defaultStatementGroup)); String replacement; String source = state.getSourceCode().toString();
int start = state.getEndPosition(members.get(o.index() - 1)); int end = state.getEndPosition(o.tree()); sb.append(state.getSourceCode(), start, end).append('\n'); fixBuilder.replace(start, end, ""); });
state.getSourceCode().subSequence(startPosition, endPosition).toString()); return describeMatch(last, fix.build());
return Optional.of(fix.delete(tree).build()); } else { String source = state.getSourceCode().toString();
private static SuggestedFix fixClass(ClassTree classTree, VisitorState state) { int startPos = ((JCTree) classTree).getStartPosition(); int endPos = ((JCTree) classTree.getMembers().get(0)).getStartPosition(); ImmutableList<ErrorProneToken> tokens = ErrorProneTokens.getTokens( state.getSourceCode().subSequence(startPos, endPos).toString(), state.context); String modifiers = getSymbol(classTree).owner.enclClass() == null ? "final class" : "static final class"; SuggestedFix.Builder fix = SuggestedFix.builder(); for (ErrorProneToken token : tokens) { if (token.kind() == TokenKind.INTERFACE) { fix.replace(startPos + token.pos(), startPos + token.endPos(), modifiers); } } return fix.build(); } }
state.getSourceCode().subSequence(state.getEndPosition(defaultCase), end).toString(), state.context) .stream()
/** Be warned, only changes method name at the declaration. */ public static SuggestedFix renameMethod( MethodTree tree, final String replacement, VisitorState state) { // Search tokens from beginning of method tree to beginning of method body. int basePos = ((JCTree) tree).getStartPosition(); int endPos = tree.getBody() != null ? ((JCTree) tree.getBody()).getStartPosition() : state.getEndPosition(tree); List<ErrorProneToken> methodTokens = ErrorProneTokens.getTokens( state.getSourceCode().subSequence(basePos, endPos).toString(), state.context); for (ErrorProneToken token : methodTokens) { if (token.kind() == TokenKind.IDENTIFIER && token.name().equals(tree.getName())) { int nameStartPosition = basePos + token.pos(); int nameEndPosition = basePos + token.endPos(); return SuggestedFix.builder() .replace(nameStartPosition, nameEndPosition, replacement) .build(); } } // Method name not found. throw new AssertionError(); }
String comments = state .getSourceCode() .subSequence(caseEndPosition(state, caseTree), next.getStartPosition()) .toString()
/** Tokenizes as little of the {@code tree} as possible to ensure we grab all the annotations. */ private static ImmutableList<ErrorProneToken> annotationTokens( Tree tree, VisitorState state, int annotationEnd) { int endPos; if (tree instanceof JCMethodDecl) { JCMethodDecl methodTree = (JCMethodDecl) tree; endPos = methodTree.getBody() == null ? state.getEndPosition(methodTree) : methodTree.getBody().getStartPosition(); } else if (tree instanceof JCVariableDecl) { endPos = ((JCVariableDecl) tree).getType().getStartPosition(); } else if (tree instanceof JCClassDecl) { JCClassDecl classTree = (JCClassDecl) tree; endPos = classTree.getMembers().isEmpty() ? state.getEndPosition(classTree) : classTree.getMembers().get(0).getStartPosition(); } else { throw new AssertionError(); } return ErrorProneTokens.getTokens( state.getSourceCode().subSequence(annotationEnd, endPos).toString(), state.context); }
state.getSourceCode().subSequence(startTokenization, state.getEndPosition(tree)).toString(); ImmutableList<ErrorProneToken> tokens = ErrorProneTokens.getTokens(source, state.context); if (previousMember == null) {
CharSequence sourceCode = state.getSourceCode(); Optional<Integer> endPosition = computeEndPosition(tree, sourceCode, state); if (!endPosition.isPresent()) {