12
12
import com .google .common .collect .ImmutableList ;
13
13
import com .google .errorprone .BugPattern ;
14
14
import com .google .errorprone .VisitorState ;
15
- import com .google .errorprone .annotations .Var ;
16
15
import com .google .errorprone .bugpatterns .BugChecker ;
17
16
import com .google .errorprone .fixes .SuggestedFix ;
18
17
import com .google .errorprone .fixes .SuggestedFixes ;
19
18
import com .google .errorprone .matchers .Description ;
20
19
import com .google .errorprone .util .ASTHelpers ;
21
20
import com .google .errorprone .util .ErrorProneToken ;
22
- import com .google .errorprone .util .ErrorProneTokens ;
23
21
import com .sun .source .tree .ClassTree ;
24
22
import com .sun .source .tree .MethodTree ;
25
23
import com .sun .source .tree .Tree ;
24
+ import com .sun .source .tree .Tree .Kind ;
26
25
import com .sun .source .tree .VariableTree ;
27
26
import com .sun .source .util .TreePath ;
28
27
import com .sun .tools .javac .parser .Tokens ;
29
- import java . util . ArrayList ;
28
+ import com . sun . tools . javac . parser . Tokens . TokenKind ;
30
29
import java .util .Comparator ;
31
30
import java .util .List ;
32
31
import java .util .Set ;
36
35
/** A {@link BugChecker} that flags classes with non-standard member ordering. */
37
36
@ AutoService (BugChecker .class )
38
37
@ BugPattern (
39
- summary = "Members should be ordered in a standard way. " ,
38
+ summary = "Members should be ordered in a standard way" ,
40
39
explanation =
41
40
"Members should be ordered in a standard way, which is: "
42
41
+ "static member variables, non-static member variables, constructors and methods." ,
@@ -50,14 +49,14 @@ public final class MemberOrdering extends BugChecker implements BugChecker.Class
50
49
/** A comparator that sorts variable and method (incl. constructors) in a standard order. */
51
50
private static final Comparator <Tree > MEMBER_SORTING =
52
51
comparing (
53
- (Tree memberTree ) -> {
54
- switch (memberTree .getKind ()) {
52
+ (Tree tree ) -> {
53
+ switch (tree .getKind ()) {
55
54
case VARIABLE :
56
- return isStatic ((VariableTree ) memberTree ) ? 1 : 2 ;
55
+ return isStatic ((VariableTree ) tree ) ? 1 : 2 ;
57
56
case METHOD :
58
- return isConstructor ((MethodTree ) memberTree ) ? 3 : 4 ;
57
+ return isConstructor ((MethodTree ) tree ) ? 3 : 4 ;
59
58
default :
60
- throw new IllegalStateException ("Unexpected kind: " + memberTree .getKind ());
59
+ throw new IllegalStateException ("Unexpected kind: " + tree .getKind ());
61
60
}
62
61
});
63
62
@@ -66,12 +65,12 @@ public MemberOrdering() {}
66
65
67
66
@ Override
68
67
public Description matchClass (ClassTree tree , VisitorState state ) {
69
- ImmutableList <MemberWithComments > membersWithComments =
68
+ ImmutableList <ClassMemberWithComments > membersWithComments =
70
69
getMembersWithComments (tree , state ).stream ()
71
- .filter (memberWithComments -> shouldBeSorted (memberWithComments .member ()))
70
+ .filter (classMemberWithComments -> shouldBeSorted (classMemberWithComments .member ()))
72
71
.collect (toImmutableList ());
73
72
74
- ImmutableList <MemberWithComments > sortedMembersWithComments =
73
+ ImmutableList <ClassMemberWithComments > sortedMembersWithComments =
75
74
ImmutableList .sortedCopyOf (
76
75
(a , b ) -> MEMBER_SORTING .compare (a .member (), b .member ()), membersWithComments );
77
76
@@ -103,13 +102,13 @@ private static boolean shouldBeSorted(Tree tree) {
103
102
}
104
103
105
104
private static SuggestedFix swapMembersWithComments (
106
- ImmutableList <MemberWithComments > memberWithComments ,
107
- ImmutableList <MemberWithComments > sortedMembersWithComments ,
105
+ ImmutableList <ClassMemberWithComments > memberWithComments ,
106
+ ImmutableList <ClassMemberWithComments > sortedMembersWithComments ,
108
107
VisitorState state ) {
109
108
SuggestedFix .Builder fix = SuggestedFix .builder ();
110
109
for (int i = 0 ; i < memberWithComments .size (); i ++) {
111
110
Tree originalMember = memberWithComments .get (i ).member ();
112
- MemberWithComments correct = sortedMembersWithComments .get (i );
111
+ ClassMemberWithComments correct = sortedMembersWithComments .get (i );
113
112
/* Technically this check is not necessary, but it avoids redundant replacements. */
114
113
if (!originalMember .equals (correct .member ())) {
115
114
String replacement =
@@ -125,62 +124,46 @@ private static SuggestedFix swapMembersWithComments(
125
124
return fix .build ();
126
125
}
127
126
128
- // XXX: Work around that `ErrorProneTokens.getTokens(memberSrc, ctx)` returns tokens not
129
- // containing the member's comments.
130
127
/** Returns the class' members with their comments. */
131
- private static ImmutableList <MemberWithComments > getMembersWithComments (
128
+ private static ImmutableList <ClassMemberWithComments > getMembersWithComments (
132
129
ClassTree classTree , VisitorState state ) {
133
130
List <ErrorProneToken > tokens =
134
- new ArrayList <> (
135
- ErrorProneTokens . getTokens ( state . getSourceForNode ( classTree ), state .context ));
131
+ state . getOffsetTokens (
132
+ ASTHelpers . getStartPosition ( classTree ), state .getEndPosition ( classTree ));
136
133
137
- ImmutableList .Builder <MemberWithComments > membersWithComments = ImmutableList .builder ();
134
+ ImmutableList .Builder <ClassMemberWithComments > membersWithComments = ImmutableList .builder ();
138
135
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 )) {
142
137
continue ;
143
138
}
144
139
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 ;
151
153
}
152
154
153
155
membersWithComments .add (
154
- new MemberWithComments (
155
- member , ImmutableList .copyOf (maybeCommentedMemberTokens .get (0 ).comments ())));
156
+ new ClassMemberWithComments (
157
+ member , ImmutableList .copyOf (memberTokens .get (0 ).comments ())));
156
158
}
157
159
return membersWithComments .build ();
158
160
}
159
161
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 {
180
163
private final Tree member ;
181
164
private final ImmutableList <Tokens .Comment > comments ;
182
165
183
- MemberWithComments (Tree member , ImmutableList <Tokens .Comment > comments ) {
166
+ ClassMemberWithComments (Tree member , ImmutableList <Tokens .Comment > comments ) {
184
167
this .member = member ;
185
168
this .comments = comments ;
186
169
}
0 commit comments