Skip to content

Commit

Permalink
New API in Position to avoid calling Tree.range().start() and `Tree.r…
Browse files Browse the repository at this point in the history
…ange().end()` everywhere
  • Loading branch information
Wohops committed Jan 5, 2023
1 parent e4d783d commit 9f23dc9
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@
*/
package org.sonar.java.model;

import java.util.Comparator;
import java.util.Optional;
import java.util.function.BiFunction;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.plugins.java.api.location.Position;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.tree.AssignmentExpressionTree;
import org.sonar.plugins.java.api.tree.BinaryExpressionTree;
Expand All @@ -35,7 +33,6 @@
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
import org.sonar.plugins.java.api.tree.MethodTree;
import org.sonar.plugins.java.api.tree.ParenthesizedTree;
import org.sonar.plugins.java.api.tree.SyntaxToken;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.UnaryExpressionTree;
import org.sonar.plugins.java.api.tree.VariableTree;
Expand All @@ -45,24 +42,6 @@ public final class ExpressionUtils {
private ExpressionUtils() {
}

public static final Comparator<Tree> TREE_START_POSITION_COMPARATOR = (t1, t2) -> startPosition(t1).compareTo(startPosition(t2));

public static Position startPosition(Tree tree) {
return startPosition(tree.firstToken());
}

public static Position endPosition(Tree tree) {
return endPosition(tree.lastToken());
}

public static Position startPosition(SyntaxToken token) {
return token.range().start();
}

public static Position endPosition(SyntaxToken token) {
return token.range().end();
}

/**
* In case of simple assignments, only the expression is evaluated, as we only use the reference to the variable to store the result.
* For SE-Based checks, only a single value should be unstacked if its the case. For other cases, two values should be unstacked.
Expand Down
28 changes: 28 additions & 0 deletions java-frontend/src/main/java/org/sonar/java/model/LineUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.sonar.plugins.java.api.location.Position;
import org.sonar.plugins.java.api.tree.SyntaxToken;
import org.sonar.plugins.java.api.tree.SyntaxTrivia;
import org.sonar.plugins.java.api.tree.Tree;

public final class LineUtils {

Expand All @@ -32,6 +36,30 @@ private LineUtils() {
// utility class
}

public static int startLine(Tree tree) {
return startLine(tree.firstToken());
}

public static int endLine(Tree tree) {
return endLine(tree.lastToken());
}

public static int startLine(SyntaxToken token) {
return Position.startOf(token).line();
}

public static int endLine(SyntaxToken token) {
return Position.endOf(token).line();
}

public static int startLine(SyntaxTrivia trivia) {
return Position.startOf(trivia).line();
}

public static int endLine(SyntaxTrivia trivia) {
return Position.endOf(trivia).line();
}

/**
* @return for example:
* "" => { "" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import org.sonar.java.ast.parser.QualifiedIdentifierListTreeImpl;
import org.sonar.java.ast.parser.TypeParameterListTreeImpl;
import org.sonarsource.analyzer.commons.collections.ListUtils;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.InternalSyntaxToken;
import org.sonar.java.model.JavaTree;
import org.sonar.java.model.Symbols;
import org.sonar.java.model.expression.IdentifierTreeImpl;
import org.sonar.plugins.java.api.location.Position;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.tree.ClassTree;
import org.sonar.plugins.java.api.tree.IdentifierTree;
Expand Down Expand Up @@ -127,7 +127,7 @@ public ClassTreeImpl completeRecordComponents(List<VariableTree> recordComponent
private static List<Tree> orderMembers(Tree.Kind kind, List<Tree> members) {
if (kind == Tree.Kind.RECORD && members.size() > 1) {
// eclipse's records members are not properly ordered
members.sort(ExpressionUtils.TREE_START_POSITION_COMPARATOR);
members.sort(Position.TREE_START_POSITION_COMPARATOR);
}
return members;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
*/
package org.sonar.plugins.java.api.location;

import java.util.Comparator;
import org.sonar.java.model.location.InternalPosition;
import org.sonar.plugins.java.api.tree.SyntaxToken;
import org.sonar.plugins.java.api.tree.SyntaxTrivia;
import org.sonar.plugins.java.api.tree.Tree;

public interface Position extends Comparable<Position> {

Comparator<Tree> TREE_START_POSITION_COMPARATOR = (t1, t2) -> startOf(t1).compareTo(startOf(t2));
int FIRST_LINE = 1;
int FIRST_COLUMN = 1;

Expand Down Expand Up @@ -54,4 +59,28 @@ static Position at(int line, int column) {

boolean isAfter(Position other);

static Position startOf(Tree tree) {
return startOf(tree.firstToken());
}

static Position endOf(Tree tree) {
return endOf(tree.lastToken());
}

static Position startOf(SyntaxTrivia trivia) {
return trivia.range().start();
}

static Position endOf(SyntaxTrivia trivia) {
return trivia.range().end();
}

static Position startOf(SyntaxToken token) {
return token.range().start();
}

static Position endOf(SyntaxToken token) {
return token.range().end();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,33 @@
*/
package org.sonar.java.model;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.sonar.plugins.java.api.tree.ClassTree;
import org.sonar.plugins.java.api.tree.CompilationUnitTree;
import org.sonar.plugins.java.api.tree.SyntaxToken;
import org.sonar.plugins.java.api.tree.SyntaxTrivia;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.java.model.LineUtils.endLine;
import static org.sonar.java.model.LineUtils.splitLines;
import static org.sonar.java.model.LineUtils.startLine;

class LineUtilsTest {

private static CompilationUnitTree tree;

@BeforeAll
static void before() {
tree = JParserTestUtils.parse("package org.foo;\n"
+ "\n"
+ "class A {\n"
+ " /*\n"
+ " * trivia\n"
+ " */\n"
+ "}");
}

@Test
void split_lines() {
assertThat(splitLines(""))
Expand Down Expand Up @@ -59,5 +79,28 @@ void split_lines() {
.containsExactly("a", "", "b", "", "c", "", "d", "", "");
}

@Test
void start_Line() {
assertThat(startLine(tree)).isEqualTo(1);

ClassTree classTree = (ClassTree) tree.types().get(0);
SyntaxToken token = classTree.firstToken();
assertThat(startLine(token)).isEqualTo(3);

SyntaxTrivia trivia = classTree.lastToken().trivias().get(0);
assertThat(startLine(trivia)).isEqualTo(4);
}

@Test
void end_Line() {
assertThat(endLine(tree)).isEqualTo(7);

ClassTree classTree = (ClassTree) tree.types().get(0);
SyntaxToken token = classTree.firstToken();
assertThat(endLine(token)).isEqualTo(3);

SyntaxTrivia trivia = classTree.lastToken().trivias().get(0);
assertThat(endLine(trivia)).isEqualTo(6);
}

}
6 changes: 6 additions & 0 deletions sonar-java-plugin/src/main/resources/static/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ The tutorial [Writing Custom Java Rules 101](https://redirect.sonarsource.com/do

#### **7.16**

* New method: `Position#startOf(Tree)`. Use this static method to get the start position of a given `Tree`. Shortcuts the usually cumbersome operation of accessing a tree start position through the normal API, with `tree.firstToken().range().start()`.
* New method: `Position#startOf(SyntaxToken)`. Use this static method to get the start position of a given `SyntaxToken`.
* New method: `Position#startOf(SyntaxTrivia)`. Use this static method to get the start position of a given `SyntaxTrivia`.
* New method: `Position#endOf(Tree)`. Use this static method to get the end position of a given `Tree`. Shortcuts the usually cumbersome operation of accessing a tree end position through the normal API, with `tree.lastToken().range().end()`.
* New method: `Position#endOf(SyntaxToken)`. Use this static method to get the end position of a given `SyntaxToken`.
* New method: `Position#endOf(SyntaxTrivia)`. Use this static method to get the end position of a given `SyntaxTrivia`.
* New method: `MethodInvocationTree#methodSymbol()`. Use this method to get the symbol of a method invocation. Returns a `MethodSymbol`.
* New method: `NewClassTree#methodSymbol()`. Use this method to get the symbol of a constructor call. Returns a `MethodSymbol`.
* Deprecated method: `MethodInvocationTree#symbol()`. Deprecated in favor of `methodSymbol()`, which has a narrower return type.
Expand Down

0 comments on commit 9f23dc9

Please sign in to comment.