1212import com .google .common .collect .ImmutableList ;
1313import com .google .errorprone .BugPattern ;
1414import com .google .errorprone .VisitorState ;
15- import com .google .errorprone .annotations .Var ;
1615import com .google .errorprone .bugpatterns .BugChecker ;
1716import com .google .errorprone .fixes .SuggestedFix ;
1817import com .google .errorprone .fixes .SuggestedFixes ;
1918import com .google .errorprone .matchers .Description ;
2019import com .google .errorprone .util .ASTHelpers ;
2120import com .google .errorprone .util .ErrorProneToken ;
22- import com .google .errorprone .util .ErrorProneTokens ;
2321import com .sun .source .tree .ClassTree ;
2422import com .sun .source .tree .MethodTree ;
2523import com .sun .source .tree .Tree ;
24+ import com .sun .source .tree .Tree .Kind ;
2625import com .sun .source .tree .VariableTree ;
2726import com .sun .source .util .TreePath ;
2827import com .sun .tools .javac .parser .Tokens ;
29- import java . util . ArrayList ;
28+ import com . sun . tools . javac . parser . Tokens . TokenKind ;
3029import java .util .Comparator ;
3130import java .util .List ;
3231import java .util .Set ;
3635/** A {@link BugChecker} that flags classes with non-standard member ordering. */
3736@ AutoService (BugChecker .class )
3837@ BugPattern (
39- summary = "Members should be ordered in a standard way. " ,
38+ summary = "Members should be ordered in a standard way" ,
4039 explanation =
4140 "Members should be ordered in a standard way, which is: "
4241 + "static member variables, non-static member variables, constructors and methods." ,
@@ -50,14 +49,14 @@ public final class MemberOrdering extends BugChecker implements BugChecker.Class
5049 /** A comparator that sorts variable and method (incl. constructors) in a standard order. */
5150 private static final Comparator <Tree > MEMBER_SORTING =
5251 comparing (
53- (Tree memberTree ) -> {
54- switch (memberTree .getKind ()) {
52+ (Tree tree ) -> {
53+ switch (tree .getKind ()) {
5554 case VARIABLE :
56- return isStatic ((VariableTree ) memberTree ) ? 1 : 2 ;
55+ return isStatic ((VariableTree ) tree ) ? 1 : 2 ;
5756 case METHOD :
58- return isConstructor ((MethodTree ) memberTree ) ? 3 : 4 ;
57+ return isConstructor ((MethodTree ) tree ) ? 3 : 4 ;
5958 default :
60- throw new IllegalStateException ("Unexpected kind: " + memberTree .getKind ());
59+ throw new IllegalStateException ("Unexpected kind: " + tree .getKind ());
6160 }
6261 });
6362
@@ -66,12 +65,12 @@ public MemberOrdering() {}
6665
6766 @ Override
6867 public Description matchClass (ClassTree tree , VisitorState state ) {
69- ImmutableList <MemberWithComments > membersWithComments =
68+ ImmutableList <ClassMemberWithComments > membersWithComments =
7069 getMembersWithComments (tree , state ).stream ()
71- .filter (memberWithComments -> shouldBeSorted (memberWithComments .member ()))
70+ .filter (classMemberWithComments -> shouldBeSorted (classMemberWithComments .member ()))
7271 .collect (toImmutableList ());
7372
74- ImmutableList <MemberWithComments > sortedMembersWithComments =
73+ ImmutableList <ClassMemberWithComments > sortedMembersWithComments =
7574 ImmutableList .sortedCopyOf (
7675 (a , b ) -> MEMBER_SORTING .compare (a .member (), b .member ()), membersWithComments );
7776
@@ -103,13 +102,13 @@ private static boolean shouldBeSorted(Tree tree) {
103102 }
104103
105104 private static SuggestedFix swapMembersWithComments (
106- ImmutableList <MemberWithComments > memberWithComments ,
107- ImmutableList <MemberWithComments > sortedMembersWithComments ,
105+ ImmutableList <ClassMemberWithComments > memberWithComments ,
106+ ImmutableList <ClassMemberWithComments > sortedMembersWithComments ,
108107 VisitorState state ) {
109108 SuggestedFix .Builder fix = SuggestedFix .builder ();
110109 for (int i = 0 ; i < memberWithComments .size (); i ++) {
111110 Tree originalMember = memberWithComments .get (i ).member ();
112- MemberWithComments correct = sortedMembersWithComments .get (i );
111+ ClassMemberWithComments correct = sortedMembersWithComments .get (i );
113112 /* Technically this check is not necessary, but it avoids redundant replacements. */
114113 if (!originalMember .equals (correct .member ())) {
115114 String replacement =
@@ -125,62 +124,46 @@ private static SuggestedFix swapMembersWithComments(
125124 return fix .build ();
126125 }
127126
128- // XXX: Work around that `ErrorProneTokens.getTokens(memberSrc, ctx)` returns tokens not
129- // containing the member's comments.
130127 /** Returns the class' members with their comments. */
131- private static ImmutableList <MemberWithComments > getMembersWithComments (
128+ private static ImmutableList <ClassMemberWithComments > getMembersWithComments (
132129 ClassTree classTree , VisitorState state ) {
133130 List <ErrorProneToken > tokens =
134- new ArrayList <> (
135- ErrorProneTokens . getTokens ( state . getSourceForNode ( classTree ), state .context ));
131+ state . getOffsetTokens (
132+ ASTHelpers . getStartPosition ( classTree ), state .getEndPosition ( classTree ));
136133
137- ImmutableList .Builder <MemberWithComments > membersWithComments = ImmutableList .builder ();
134+ ImmutableList .Builder <ClassMemberWithComments > membersWithComments = ImmutableList .builder ();
138135 for (Tree member : classTree .getMembers ()) {
139- ImmutableList <ErrorProneToken > memberTokens =
140- ErrorProneTokens .getTokens (state .getSourceForNode (member ), state .context );
141- if (memberTokens .isEmpty () || memberTokens .get (0 ).kind () == Tokens .TokenKind .EOF ) {
136+ if (!shouldBeSorted (member )) {
142137 continue ;
143138 }
144139
145- @ Var
146- ImmutableList <ErrorProneToken > maybeCommentedMemberTokens =
147- ImmutableList .copyOf (tokens .subList (0 , memberTokens .size ()));
148- while (!areTokenListsMatching (memberTokens , maybeCommentedMemberTokens )) {
149- tokens .remove (0 );
150- maybeCommentedMemberTokens = ImmutableList .copyOf (tokens .subList (0 , memberTokens .size ()));
140+ /* We start at the previous token's end position to cover any possible comments. */
141+ int memberStartPos = ASTHelpers .getStartPosition (member );
142+ int startPos =
143+ tokens .stream ()
144+ .map (ErrorProneToken ::endPos )
145+ .filter (i -> i < memberStartPos )
146+ .reduce ((first , second ) -> second )
147+ .orElse (memberStartPos );
148+
149+ ImmutableList <ErrorProneToken > memberTokens =
150+ ImmutableList .copyOf (state .getOffsetTokens (startPos , state .getEndPosition (member )));
151+ if (memberTokens .isEmpty () || memberTokens .get (0 ).kind () == TokenKind .EOF ) {
152+ continue ;
151153 }
152154
153155 membersWithComments .add (
154- new MemberWithComments (
155- member , ImmutableList .copyOf (maybeCommentedMemberTokens .get (0 ).comments ())));
156+ new ClassMemberWithComments (
157+ member , ImmutableList .copyOf (memberTokens .get (0 ).comments ())));
156158 }
157159 return membersWithComments .build ();
158160 }
159161
160- /**
161- * Checks whether two lists of error-prone tokens are 'equal' without considering their comments.
162- */
163- private static boolean areTokenListsMatching (
164- ImmutableList <ErrorProneToken > tokens , ImmutableList <ErrorProneToken > memberTokens ) {
165- if (tokens .size () != memberTokens .size ()) {
166- return false ;
167- }
168- for (int i = 0 ; i < tokens .size () - 1 /* EOF */ ; i ++) {
169- if (tokens .get (i ).kind () != memberTokens .get (i ).kind ()
170- || tokens .get (i ).hasName () != memberTokens .get (i ).hasName ()
171- || (tokens .get (i ).hasName ()
172- && !tokens .get (i ).name ().equals (memberTokens .get (i ).name ()))) {
173- return false ;
174- }
175- }
176- return true ;
177- }
178-
179- private static final class MemberWithComments {
162+ private static final class ClassMemberWithComments {
180163 private final Tree member ;
181164 private final ImmutableList <Tokens .Comment > comments ;
182165
183- MemberWithComments (Tree member , ImmutableList <Tokens .Comment > comments ) {
166+ ClassMemberWithComments (Tree member , ImmutableList <Tokens .Comment > comments ) {
184167 this .member = member ;
185168 this .comments = comments ;
186169 }
0 commit comments