21
21
import java .io .Serializable ;
22
22
import java .lang .reflect .InvocationTargetException ;
23
23
import java .lang .reflect .Method ;
24
+ import java .util .Arrays ;
24
25
import java .util .Objects ;
25
26
26
27
import com .diffplug .spotless .*;
28
+ import javax .annotation .Nullable ;
27
29
28
30
/**
29
31
* Wraps up <a href="https://github.com/facebookincubator/ktfmt">ktfmt</a> as a FormatterStep.
@@ -64,6 +66,14 @@ String getSince() {
64
66
65
67
private static final String DROPBOX_STYLE_METHOD = "dropboxStyle" ;
66
68
69
+ private static final String FORMATTING_OPTIONS_METHOD_COPY = "copy" ;
70
+ private static final String FORMATTING_OPTIONS_METHOD_GET_STYLE = "getStyle" ;
71
+ private static final String FORMATTING_OPTIONS_METHOD_GET_MAX_WIDTH = "getMaxWidth" ;
72
+ private static final String FORMATTING_OPTIONS_METHOD_GET_BLOCK_INDENT = "getBlockIndent" ;
73
+ private static final String FORMATTING_OPTIONS_METHOD_GET_CONTINUATION_INDENT = "getContinuationIndent" ;
74
+ private static final String FORMATTING_OPTIONS_METHOD_GET_REMOVE_UNUSED_IMPORTS = "getRemoveUnusedImports" ;
75
+ private static final String FORMATTING_OPTIONS_METHOD_GET_DEBUGGING_PRINT_OPS_AFTER_FORMATTING = "getDebuggingPrintOpsAfterFormatting" ;
76
+
67
77
/**
68
78
* The <code>format</code> method is available in the link below.
69
79
*
@@ -78,16 +88,16 @@ public static FormatterStep create(Provisioner provisioner) {
78
88
79
89
/** Creates a step which formats everything - code, import order, and unused imports. */
80
90
public static FormatterStep create (String version , Provisioner provisioner ) {
81
- return create (version , provisioner , DEFAULT );
91
+ return create (version , provisioner , null , DEFAULT );
82
92
}
83
93
84
94
/** Creates a step which formats everything - code, import order, and unused imports. */
85
- public static FormatterStep create (String version , Provisioner provisioner , Style style ) {
95
+ public static FormatterStep create (String version , Provisioner provisioner , @ Nullable Integer maxWidth , Style style ) {
86
96
Objects .requireNonNull (version , "version" );
87
97
Objects .requireNonNull (provisioner , "provisioner" );
88
98
Objects .requireNonNull (style , "style" );
89
99
return FormatterStep .createLazy (
90
- NAME , () -> new State (version , provisioner , style ), State ::createFormat );
100
+ NAME , () -> new State (version , provisioner , maxWidth , style ), State ::createFormat );
91
101
}
92
102
93
103
public static String defaultVersion () {
@@ -104,16 +114,22 @@ static final class State implements Serializable {
104
114
private final String version ;
105
115
106
116
private final String pkg ;
117
+ /**
118
+ * Option that allows change line width before breaking
119
+ */
120
+ @ Nullable
121
+ private final Integer maxWidth ;
107
122
/**
108
123
* Option that allows to apply formatting options to perform a 4 spaces block and continuation indent.
109
124
*/
110
125
private final Style style ;
111
126
/** The jar that contains the formatter. */
112
127
final JarState jarState ;
113
128
114
- State (String version , Provisioner provisioner , Style style ) throws IOException {
129
+ State (String version , Provisioner provisioner , @ Nullable Integer maxWidth , Style style ) throws IOException {
115
130
this .version = version ;
116
131
this .pkg = PACKAGE ;
132
+ this .maxWidth = maxWidth ;
117
133
this .style = style ;
118
134
this .jarState = JarState .from (MAVEN_COORDINATE + version , provisioner );
119
135
}
@@ -122,29 +138,55 @@ FormatterFunc createFormat() throws Exception {
122
138
ClassLoader classLoader = jarState .getClassLoader ();
123
139
return input -> {
124
140
try {
125
- if (style == DEFAULT ) {
126
- Method formatterMethod = getFormatterClazz (classLoader ).getMethod (FORMATTER_METHOD , String .class );
127
- return (String ) formatterMethod .invoke (getFormatterClazz (classLoader ), input );
128
- } else {
129
- Method formatterMethod = getFormatterClazz (classLoader ).getMethod (FORMATTER_METHOD , getFormattingOptionsClazz (classLoader ),
130
- String .class );
131
- Object formattingOptions = getCustomFormattingOptions (classLoader , style );
132
- return (String ) formatterMethod .invoke (getFormatterClazz (classLoader ), formattingOptions , input );
133
- }
141
+ Method formatterMethod = getFormatterClazz (classLoader ).getMethod (FORMATTER_METHOD , getFormattingOptionsClazz (classLoader ),
142
+ String .class );
143
+ Object formattingOptions = getCustomFormattingOptions (classLoader , maxWidth , style );
144
+ return (String ) formatterMethod .invoke (getFormatterClazz (classLoader ), formattingOptions , input );
134
145
} catch (InvocationTargetException e ) {
135
146
throw ThrowingEx .unwrapCause (e );
136
147
}
137
148
};
138
149
}
139
150
140
- private Object getCustomFormattingOptions (ClassLoader classLoader , Style style ) throws Exception {
151
+ private Object getCustomFormattingOptions (ClassLoader classLoader , @ Nullable Integer maxWidth , Style style ) throws Exception {
141
152
if (BadSemver .version (version ) < BadSemver .version (style .since )) {
142
153
throw new IllegalStateException (String .format ("The style %s is available from version %s (current version: %s)" , style .name (), style .since , version ));
143
154
}
144
155
145
156
try {
146
157
// ktfmt v0.19 and later
147
- return getFormatterClazz (classLoader ).getField (style .getFormat ()).get (null );
158
+ Object formattingOptionVariable ;
159
+ if (style == DEFAULT ) {
160
+ formattingOptionVariable = getFormattingOptionsClazz (classLoader ).getDeclaredConstructor ().newInstance ();
161
+ } else {
162
+ formattingOptionVariable = getFormatterClazz (classLoader ).getField (style .getFormat ()).get (null );
163
+ }
164
+
165
+ if (maxWidth != null ) {
166
+ if (BadSemver .version (version ) < BadSemver .version (0 , 31 )) {
167
+ throw new IllegalStateException ("Max width configuration supported only for ktfmt 0.31 and later" );
168
+ }
169
+
170
+ Class <?> formattingOptionsClass = getFormattingOptionsClazz (classLoader );
171
+ Object styleValue = formattingOptionsClass .getMethod (FORMATTING_OPTIONS_METHOD_GET_STYLE ).invoke (formattingOptionVariable );
172
+ Object maxWidthValue = formattingOptionsClass .getMethod (FORMATTING_OPTIONS_METHOD_GET_MAX_WIDTH ).invoke (formattingOptionVariable );
173
+ Object blockIndentValue = formattingOptionsClass .getMethod (FORMATTING_OPTIONS_METHOD_GET_BLOCK_INDENT ).invoke (formattingOptionVariable );
174
+ Object continuationIndentValue = formattingOptionsClass .getMethod (FORMATTING_OPTIONS_METHOD_GET_CONTINUATION_INDENT ).invoke (formattingOptionVariable );
175
+ Object removeUnusedImportsValue = formattingOptionsClass .getMethod (FORMATTING_OPTIONS_METHOD_GET_REMOVE_UNUSED_IMPORTS ).invoke (formattingOptionVariable );
176
+ Object debuggingPrintOpsAfterFormattingValue = formattingOptionsClass .getMethod (FORMATTING_OPTIONS_METHOD_GET_DEBUGGING_PRINT_OPS_AFTER_FORMATTING ).invoke (formattingOptionVariable );
177
+
178
+ Method copyFormattingOption = Arrays .stream (formattingOptionsClass .getDeclaredMethods ())
179
+ .filter (method -> FORMATTING_OPTIONS_METHOD_COPY .equals (method .getName ())).findFirst ().get ();
180
+ formattingOptionVariable = copyFormattingOption .invoke (formattingOptionVariable ,
181
+ styleValue ,
182
+ maxWidth > 0 ? maxWidth : maxWidthValue ,
183
+ blockIndentValue ,
184
+ continuationIndentValue ,
185
+ removeUnusedImportsValue ,
186
+ debuggingPrintOpsAfterFormattingValue );
187
+ }
188
+
189
+ return formattingOptionVariable ;
148
190
} catch (NoSuchFieldException ignored ) {}
149
191
150
192
// fallback to old, pre-0.19 ktfmt interface.
0 commit comments