14
14
15
15
package com .google .googlejavaformat .java ;
16
16
17
+ import static com .google .common .collect .ImmutableList .toImmutableList ;
17
18
import static com .google .common .collect .Iterables .getLast ;
18
19
import static com .google .common .collect .Iterables .getOnlyElement ;
19
20
import static com .google .googlejavaformat .Doc .FillMode .INDEPENDENT ;
84
85
import com .sun .source .tree .AssertTree ;
85
86
import com .sun .source .tree .AssignmentTree ;
86
87
import com .sun .source .tree .BinaryTree ;
88
+ import com .sun .source .tree .BindingPatternTree ;
87
89
import com .sun .source .tree .BlockTree ;
88
90
import com .sun .source .tree .BreakTree ;
91
+ import com .sun .source .tree .CaseLabelTree ;
89
92
import com .sun .source .tree .CaseTree ;
90
93
import com .sun .source .tree .CatchTree ;
91
94
import com .sun .source .tree .ClassTree ;
125
128
import com .sun .source .tree .RequiresTree ;
126
129
import com .sun .source .tree .ReturnTree ;
127
130
import com .sun .source .tree .StatementTree ;
131
+ import com .sun .source .tree .SwitchExpressionTree ;
128
132
import com .sun .source .tree .SwitchTree ;
129
133
import com .sun .source .tree .SynchronizedTree ;
130
134
import com .sun .source .tree .ThrowTree ;
138
142
import com .sun .source .tree .VariableTree ;
139
143
import com .sun .source .tree .WhileLoopTree ;
140
144
import com .sun .source .tree .WildcardTree ;
145
+ import com .sun .source .tree .YieldTree ;
141
146
import com .sun .source .util .TreePath ;
142
147
import com .sun .source .util .TreePathScanner ;
143
148
import com .sun .tools .javac .code .Flags ;
144
149
import com .sun .tools .javac .tree .JCTree ;
145
150
import com .sun .tools .javac .tree .JCTree .JCMethodDecl ;
151
+ import com .sun .tools .javac .tree .TreeInfo ;
146
152
import com .sun .tools .javac .tree .TreeScanner ;
147
153
import java .util .ArrayDeque ;
148
154
import java .util .ArrayList ;
@@ -410,7 +416,17 @@ public Void visitCompilationUnit(CompilationUnitTree node, Void unused) {
410
416
return null ;
411
417
}
412
418
413
- protected void handleModule (boolean afterFirstToken , CompilationUnitTree node ) {}
419
+ protected void handleModule (boolean afterFirstToken , CompilationUnitTree node ) {
420
+ ModuleTree module = node .getModule ();
421
+ if (module != null ) {
422
+ if (afterFirstToken ) {
423
+ builder .blankLineWanted (YES );
424
+ }
425
+ markForPartialFormat ();
426
+ visitModule (module , null );
427
+ builder .forcedBreak ();
428
+ }
429
+ }
414
430
415
431
/** Skips over extra semi-colons at the top-level, or in a class member declaration lists. */
416
432
protected void dropEmptyDeclarations () {
@@ -436,6 +452,9 @@ public Void visitClass(ClassTree tree, Void unused) {
436
452
case ENUM :
437
453
visitEnumDeclaration (tree );
438
454
break ;
455
+ case RECORD :
456
+ visitRecordDeclaration (tree );
457
+ break ;
439
458
default :
440
459
throw new AssertionError (tree .getKind ());
441
460
}
@@ -928,6 +947,69 @@ public boolean visitEnumDeclaration(ClassTree node) {
928
947
return false ;
929
948
}
930
949
950
+ public void visitRecordDeclaration (ClassTree node ) {
951
+ sync (node );
952
+ typeDeclarationModifiers (node .getModifiers ());
953
+ Verify .verify (node .getExtendsClause () == null );
954
+ boolean hasSuperInterfaceTypes = !node .getImplementsClause ().isEmpty ();
955
+ token ("record" );
956
+ builder .space ();
957
+ visit (node .getSimpleName ());
958
+ if (!node .getTypeParameters ().isEmpty ()) {
959
+ token ("<" );
960
+ }
961
+ builder .open (plusFour );
962
+ {
963
+ if (!node .getTypeParameters ().isEmpty ()) {
964
+ typeParametersRest (node .getTypeParameters (), hasSuperInterfaceTypes ? plusFour : ZERO );
965
+ }
966
+ ImmutableList <JCTree .JCVariableDecl > parameters = JavaInputAstVisitor .recordVariables (node );
967
+ token ("(" );
968
+ if (!parameters .isEmpty ()) {
969
+ // Break before args.
970
+ builder .breakToFill ("" );
971
+ }
972
+ // record headers can't declare receiver parameters
973
+ visitFormals (/* receiver= */ Optional .empty (), parameters );
974
+ token (")" );
975
+ if (hasSuperInterfaceTypes ) {
976
+ builder .breakToFill (" " );
977
+ builder .open (node .getImplementsClause ().size () > 1 ? plusFour : ZERO );
978
+ token ("implements" );
979
+ builder .space ();
980
+ boolean afterFirstToken = false ;
981
+ for (Tree superInterfaceType : node .getImplementsClause ()) {
982
+ if (afterFirstToken ) {
983
+ token ("," );
984
+ builder .breakOp (" " );
985
+ }
986
+ scan (superInterfaceType , null );
987
+ afterFirstToken = true ;
988
+ }
989
+ builder .close ();
990
+ }
991
+ }
992
+ builder .close ();
993
+ if (node .getMembers () == null ) {
994
+ token (";" );
995
+ } else {
996
+ ImmutableList <Tree > members =
997
+ node .getMembers ().stream ()
998
+ .filter (t -> (TreeInfo .flags ((JCTree ) t ) & Flags .GENERATED_MEMBER ) == 0 )
999
+ .collect (toImmutableList ());
1000
+ addBodyDeclarations (members , BracesOrNot .YES , FirstDeclarationsOrNot .YES );
1001
+ }
1002
+ dropEmptyDeclarations ();
1003
+ }
1004
+
1005
+ private static ImmutableList <JCTree .JCVariableDecl > recordVariables (ClassTree node ) {
1006
+ return node .getMembers ().stream ()
1007
+ .filter (JCTree .JCVariableDecl .class ::isInstance )
1008
+ .map (JCTree .JCVariableDecl .class ::cast )
1009
+ .filter (m -> (m .mods .flags & RECORD ) == RECORD )
1010
+ .collect (toImmutableList ());
1011
+ }
1012
+
931
1013
@ Override
932
1014
public Void visitMemberReference (MemberReferenceTree node , Void unused ) {
933
1015
builder .open (plusFour );
@@ -1199,7 +1281,11 @@ public Void visitInstanceOf(InstanceOfTree node, Void unused) {
1199
1281
builder .open (ZERO );
1200
1282
token ("instanceof" );
1201
1283
builder .breakOp (" " );
1202
- scan (node .getType (), null );
1284
+ if (node .getPattern () != null ) {
1285
+ scan (node .getPattern (), null );
1286
+ } else {
1287
+ scan (node .getType (), null );
1288
+ }
1203
1289
builder .close ();
1204
1290
builder .close ();
1205
1291
return null ;
@@ -1874,18 +1960,69 @@ public Void visitCase(CaseTree node, Void unused) {
1874
1960
sync (node );
1875
1961
markForPartialFormat ();
1876
1962
builder .forcedBreak ();
1877
- if (node .getExpression () == null ) {
1963
+ List <? extends CaseLabelTree > labels = node .getLabels ();
1964
+ boolean isDefault =
1965
+ labels .size () == 1 && getOnlyElement (labels ).getKind ().name ().equals ("DEFAULT_CASE_LABEL" );
1966
+ builder .open (node .getCaseKind ().equals (CaseTree .CaseKind .RULE ) ? plusFour : ZERO );
1967
+ if (isDefault ) {
1878
1968
token ("default" , ZERO );
1879
- token (":" );
1880
1969
} else {
1881
1970
token ("case" , ZERO );
1971
+ builder .open (ZERO );
1882
1972
builder .space ();
1883
- scan (node .getExpression (), null );
1884
- token (":" );
1973
+ boolean afterFirstToken = false ;
1974
+ for (Tree expression : labels ) {
1975
+ if (afterFirstToken ) {
1976
+ token ("," );
1977
+ builder .breakOp (" " );
1978
+ }
1979
+ scan (expression , null );
1980
+ afterFirstToken = true ;
1981
+ }
1982
+ builder .close ();
1983
+ }
1984
+
1985
+ final ExpressionTree guard = getGuard (node );
1986
+ if (guard != null ) {
1987
+ builder .breakToFill (" " );
1988
+ token ("when" );
1989
+ builder .space ();
1990
+ scan (guard , null );
1991
+ }
1992
+
1993
+ switch (node .getCaseKind ()) {
1994
+ case STATEMENT :
1995
+ token (":" );
1996
+ builder .open (plusTwo );
1997
+ visitStatements (node .getStatements ());
1998
+ builder .close ();
1999
+ builder .close ();
2000
+ break ;
2001
+ case RULE :
2002
+ builder .space ();
2003
+ token ("-" );
2004
+ token (">" );
2005
+ if (node .getBody ().getKind () == BLOCK ) {
2006
+ builder .close ();
2007
+ builder .space ();
2008
+ // Explicit call with {@link CollapseEmptyOrNot.YES} to handle empty case blocks.
2009
+ visitBlock (
2010
+ (BlockTree ) node .getBody (),
2011
+ CollapseEmptyOrNot .YES ,
2012
+ AllowLeadingBlankLine .NO ,
2013
+ AllowTrailingBlankLine .NO );
2014
+ } else {
2015
+ builder .breakOp (" " );
2016
+ scan (node .getBody (), null );
2017
+ builder .close ();
2018
+ }
2019
+ builder .guessToken (";" );
2020
+ break ;
1885
2021
}
1886
- builder .open (plusTwo );
1887
- visitStatements (node .getStatements ());
1888
- builder .close ();
2022
+ return null ;
2023
+ }
2024
+
2025
+ protected ExpressionTree getGuard (final CaseTree node ) {
1889
2026
return null ;
1890
2027
}
1891
2028
@@ -2022,7 +2159,7 @@ public Void visitTry(TryTree node, Void unused) {
2022
2159
public void visitClassDeclaration (ClassTree node ) {
2023
2160
sync (node );
2024
2161
typeDeclarationModifiers (node .getModifiers ());
2025
- List <? extends Tree > permitsTypes = getPermitsClause (node );
2162
+ List <? extends Tree > permitsTypes = node . getPermitsClause ();
2026
2163
boolean hasSuperclassType = node .getExtendsClause () != null ;
2027
2164
boolean hasSuperInterfaceTypes = !node .getImplementsClause ().isEmpty ();
2028
2165
boolean hasPermitsTypes = !permitsTypes .isEmpty ();
@@ -3800,11 +3937,6 @@ protected void addBodyDeclarations(
3800
3937
}
3801
3938
}
3802
3939
3803
- /** Gets the permits clause for the given node. This is only available in Java 15 and later. */
3804
- protected List <? extends Tree > getPermitsClause (ClassTree node ) {
3805
- return ImmutableList .of ();
3806
- }
3807
-
3808
3940
private void classDeclarationTypeList (String token , List <? extends Tree > types ) {
3809
3941
if (types .isEmpty ()) {
3810
3942
return ;
@@ -3966,4 +4098,40 @@ final BreakTag genSym() {
3966
4098
public final String toString () {
3967
4099
return MoreObjects .toStringHelper (this ).add ("builder" , builder ).toString ();
3968
4100
}
4101
+
4102
+ @ Override
4103
+ public Void visitBindingPattern (BindingPatternTree node , Void unused ) {
4104
+ sync (node );
4105
+ VariableTree variableTree = node .getVariable ();
4106
+ declareOne (
4107
+ DeclarationKind .PARAMETER ,
4108
+ Direction .HORIZONTAL ,
4109
+ Optional .of (variableTree .getModifiers ()),
4110
+ variableTree .getType (),
4111
+ variableTree .getName (),
4112
+ /* op= */ "" ,
4113
+ /* equals= */ "" ,
4114
+ /* initializer= */ Optional .empty (),
4115
+ /* trailing= */ Optional .empty (),
4116
+ /* receiverExpression= */ Optional .empty (),
4117
+ /* typeWithDims= */ Optional .empty ());
4118
+ return null ;
4119
+ }
4120
+
4121
+ @ Override
4122
+ public Void visitYield (YieldTree node , Void aVoid ) {
4123
+ sync (node );
4124
+ token ("yield" );
4125
+ builder .space ();
4126
+ scan (node .getValue (), null );
4127
+ token (";" );
4128
+ return null ;
4129
+ }
4130
+
4131
+ @ Override
4132
+ public Void visitSwitchExpression (SwitchExpressionTree node , Void aVoid ) {
4133
+ sync (node );
4134
+ visitSwitch (node .getExpression (), node .getCases ());
4135
+ return null ;
4136
+ }
3969
4137
}
0 commit comments