@@ -63,8 +63,9 @@ public static int version() {
63
63
public static class Support <V > {
64
64
private final String fmtName ;
65
65
private final Comparator <? super V > fmtVersionComparator ;
66
- private final NavigableMap <Integer , V > jvm2fmtVersion ;
67
- private final NavigableMap <V , Integer > fmt2jvmVersion ;
66
+ private final NavigableMap <Integer , V > jvm2fmtMaxVersion ;
67
+ private final NavigableMap <Integer , V > jvm2fmtMinVersion ;
68
+ private final NavigableMap <V , Integer > fmtMaxVersion2jvmVersion ;
68
69
69
70
private Support (String fromatterName ) {
70
71
this (fromatterName , new SemanticVersionComparator <V >());
@@ -73,40 +74,60 @@ private Support(String fromatterName) {
73
74
private Support (String formatterName , Comparator <? super V > formatterVersionComparator ) {
74
75
fmtName = formatterName ;
75
76
fmtVersionComparator = formatterVersionComparator ;
76
- jvm2fmtVersion = new TreeMap <Integer , V >();
77
- fmt2jvmVersion = new TreeMap <V , Integer >(formatterVersionComparator );
77
+ jvm2fmtMaxVersion = new TreeMap <>();
78
+ jvm2fmtMinVersion = new TreeMap <>();
79
+ fmtMaxVersion2jvmVersion = new TreeMap <>(formatterVersionComparator );
78
80
}
79
81
80
82
/**
81
- * Add supported formatter version
83
+ * Add maximum supported formatter version
82
84
* @param minimumJvmVersion Minimum Java version required
83
85
* @param maxFormatterVersion Maximum formatter version supported by the Java version
84
86
* @return this
85
87
*/
86
88
public Support <V > add (int minimumJvmVersion , V maxFormatterVersion ) {
87
89
Objects .requireNonNull (maxFormatterVersion );
88
- if (null != jvm2fmtVersion .put (minimumJvmVersion , maxFormatterVersion )) {
90
+ if (null != jvm2fmtMaxVersion .put (minimumJvmVersion , maxFormatterVersion )) {
89
91
throw new IllegalArgumentException (String .format ("Added duplicate entry for JVM %d+." , minimumJvmVersion ));
90
92
}
91
- if (null != fmt2jvmVersion .put (maxFormatterVersion , minimumJvmVersion )) {
93
+ if (null != fmtMaxVersion2jvmVersion .put (maxFormatterVersion , minimumJvmVersion )) {
92
94
throw new IllegalArgumentException (String .format ("Added duplicate entry for formatter version %s." , maxFormatterVersion ));
93
95
}
96
+ verifyVersionRangesDoNotIntersect (jvm2fmtMaxVersion , minimumJvmVersion , maxFormatterVersion );
97
+ return this ;
98
+ }
99
+
100
+ public Support <V > addMin (int minimumJvmVersion , V minFormatterVersion ) {
101
+ Objects .requireNonNull (minFormatterVersion );
102
+ if (null != jvm2fmtMinVersion .put (minimumJvmVersion , minFormatterVersion )) {
103
+ throw new IllegalArgumentException (String .format ("Added duplicate entry for JVM %d+." , minimumJvmVersion ));
104
+ }
105
+ verifyVersionRangesDoNotIntersect (jvm2fmtMinVersion , minimumJvmVersion , minFormatterVersion );
106
+ return this ;
107
+ }
108
+
109
+ private void verifyVersionRangesDoNotIntersect (NavigableMap <Integer , V > jvm2fmtVersion , int minimumJvmVersion , V formatterVersion ) {
94
110
Map .Entry <Integer , V > lower = jvm2fmtVersion .lowerEntry (minimumJvmVersion );
95
- if ((null != lower ) && (fmtVersionComparator .compare (maxFormatterVersion , lower .getValue ()) <= 0 )) {
96
- throw new IllegalArgumentException (String .format ("%d/%s should be lower than %d/%s" , minimumJvmVersion , maxFormatterVersion , lower .getKey (), lower .getValue ()));
111
+ if ((null != lower ) && (fmtVersionComparator .compare (formatterVersion , lower .getValue ()) <= 0 )) {
112
+ throw new IllegalArgumentException (String .format ("%d/%s should be lower than %d/%s" , minimumJvmVersion , formatterVersion , lower .getKey (), lower .getValue ()));
97
113
}
98
114
Map .Entry <Integer , V > higher = jvm2fmtVersion .higherEntry (minimumJvmVersion );
99
- if ((null != higher ) && (fmtVersionComparator .compare (maxFormatterVersion , higher .getValue ()) >= 0 )) {
100
- throw new IllegalArgumentException (String .format ("%d/%s should be higher than %d/%s" , minimumJvmVersion , maxFormatterVersion , higher .getKey (), higher .getValue ()));
115
+ if ((null != higher ) && (fmtVersionComparator .compare (formatterVersion , higher .getValue ()) >= 0 )) {
116
+ throw new IllegalArgumentException (String .format ("%d/%s should be higher than %d/%s" , minimumJvmVersion , formatterVersion , higher .getKey (), higher .getValue ()));
101
117
}
102
- return this ;
103
118
}
104
119
105
120
/** @return Highest formatter version recommended for this JVM (null, if JVM not supported) */
106
121
@ Nullable
107
122
public V getRecommendedFormatterVersion () {
108
- Integer configuredJvmVersionOrNull = jvm2fmtVersion .floorKey (Jvm .version ());
109
- return (null == configuredJvmVersionOrNull ) ? null : jvm2fmtVersion .get (configuredJvmVersionOrNull );
123
+ Integer configuredJvmVersionOrNull = jvm2fmtMaxVersion .floorKey (Jvm .version ());
124
+ return (null == configuredJvmVersionOrNull ) ? null : jvm2fmtMaxVersion .get (configuredJvmVersionOrNull );
125
+ }
126
+
127
+ @ Nullable
128
+ public V getMinimumRequiredFormatterVersion () {
129
+ Integer configuredJvmVersionOrNull = jvm2fmtMinVersion .floorKey (Jvm .version ());
130
+ return (null == configuredJvmVersionOrNull ) ? null : jvm2fmtMinVersion .get (configuredJvmVersionOrNull );
110
131
}
111
132
112
133
/**
@@ -123,10 +144,17 @@ public void assertFormatterSupported(V formatterVersion) {
123
144
}
124
145
125
146
private String buildUnsupportedFormatterMessage (V fmtVersion ) {
147
+ // check if the jvm version is to low for the formatter version
126
148
int requiredJvmVersion = getRequiredJvmVersion (fmtVersion );
127
149
if (Jvm .version () < requiredJvmVersion ) {
128
150
return buildUpgradeJvmMessage (fmtVersion ) + "Upgrade your JVM or try " + toString ();
129
151
}
152
+ // check if the formatter version is too low for the jvm version
153
+ V minimumFormatterVersion = getMinimumRequiredFormatterVersion ();
154
+ if ((null != minimumFormatterVersion ) && (fmtVersionComparator .compare (fmtVersion , minimumFormatterVersion ) < 0 )) {
155
+ return String .format ("You are running Spotless on JVM %d, which requires %s of at least %s (you are using %s).%n" , Jvm .version (), fmtName , minimumFormatterVersion , fmtVersion );
156
+ }
157
+ // otherwise all is well
130
158
return "" ;
131
159
}
132
160
@@ -137,7 +165,7 @@ private String buildUpgradeJvmMessage(V fmtVersion) {
137
165
if (null != recommendedFmtVersionOrNull ) {
138
166
builder .append (String .format (", which limits you to %s %s.%n" , fmtName , recommendedFmtVersionOrNull ));
139
167
} else {
140
- Entry <V , Integer > nextFmtVersionOrNull = fmt2jvmVersion .ceilingEntry (fmtVersion );
168
+ Entry <V , Integer > nextFmtVersionOrNull = fmtMaxVersion2jvmVersion .ceilingEntry (fmtVersion );
141
169
if (null != nextFmtVersionOrNull ) {
142
170
builder .append (String .format (". %s %s requires JVM %d+" , fmtName , fmtVersion , nextFmtVersionOrNull .getValue ()));
143
171
}
@@ -147,12 +175,12 @@ private String buildUpgradeJvmMessage(V fmtVersion) {
147
175
}
148
176
149
177
private int getRequiredJvmVersion (V fmtVersion ) {
150
- Entry <V , Integer > entry = fmt2jvmVersion .ceilingEntry (fmtVersion );
178
+ Entry <V , Integer > entry = fmtMaxVersion2jvmVersion .ceilingEntry (fmtVersion );
151
179
if (null == entry ) {
152
- entry = fmt2jvmVersion .lastEntry ();
180
+ entry = fmtMaxVersion2jvmVersion .lastEntry ();
153
181
}
154
182
if (null != entry ) {
155
- V maxKnownFmtVersion = jvm2fmtVersion .get (entry .getValue ());
183
+ V maxKnownFmtVersion = jvm2fmtMaxVersion .get (entry .getValue ());
156
184
if (fmtVersionComparator .compare (fmtVersion , maxKnownFmtVersion ) <= 0 ) {
157
185
return entry .getValue ();
158
186
}
@@ -170,15 +198,15 @@ public FormatterFunc suggestLaterVersionOnError(V formatterVersion, FormatterFun
170
198
Objects .requireNonNull (formatterVersion );
171
199
Objects .requireNonNull (originalFunc );
172
200
final String hintUnsupportedProblem = buildUnsupportedFormatterMessage (formatterVersion );
173
- final String proposeDiffererntFormatter = hintUnsupportedProblem .isEmpty () ? buildUpgradeFormatterMessage (formatterVersion ) : hintUnsupportedProblem ;
174
- return proposeDiffererntFormatter .isEmpty () ? originalFunc : new FormatterFunc () {
201
+ final String proposeDifferentFormatter = hintUnsupportedProblem .isEmpty () ? buildUpgradeFormatterMessage (formatterVersion ) : hintUnsupportedProblem ;
202
+ return proposeDifferentFormatter .isEmpty () ? originalFunc : new FormatterFunc () {
175
203
176
204
@ Override
177
205
public String apply (String unix , File file ) throws Exception {
178
206
try {
179
207
return originalFunc .apply (unix , file );
180
208
} catch (Exception e ) {
181
- throw new Exception (proposeDiffererntFormatter , e );
209
+ throw new Exception (proposeDifferentFormatter , e );
182
210
}
183
211
}
184
212
@@ -187,7 +215,7 @@ public String apply(String input) throws Exception {
187
215
try {
188
216
return originalFunc .apply (input );
189
217
} catch (Exception e ) {
190
- throw new Exception (proposeDiffererntFormatter , e );
218
+ throw new Exception (proposeDifferentFormatter , e );
191
219
}
192
220
}
193
221
@@ -196,16 +224,25 @@ public String apply(String input) throws Exception {
196
224
197
225
private String buildUpgradeFormatterMessage (V fmtVersion ) {
198
226
StringBuilder builder = new StringBuilder ();
227
+ // check if the formatter is not supported on this jvm
228
+ V minimumFormatterVersion = getMinimumRequiredFormatterVersion ();
199
229
V recommendedFmtVersionOrNull = getRecommendedFormatterVersion ();
200
- if (null != recommendedFmtVersionOrNull && (fmtVersionComparator .compare (fmtVersion , recommendedFmtVersionOrNull ) < 0 )) {
230
+ if ((null != minimumFormatterVersion ) && (fmtVersionComparator .compare (fmtVersion , minimumFormatterVersion ) < 0 )) {
231
+ builder .append (String .format ("You are running Spotless on JVM %d, which requires %s of at least %s.%n" , Jvm .version (), fmtName , minimumFormatterVersion ));
232
+ builder .append (String .format ("You are using %s %s.%n" , fmtName , fmtVersion ));
233
+ if (null != recommendedFmtVersionOrNull ) {
234
+ builder .append (String .format ("%s %s is the recommended version, which may have fixed this problem.%n" , fmtName , recommendedFmtVersionOrNull ));
235
+ }
236
+ // check if the formatter is outdated on this jvm
237
+ } else if (null != recommendedFmtVersionOrNull && (fmtVersionComparator .compare (fmtVersion , recommendedFmtVersionOrNull ) < 0 )) {
201
238
builder .append (String .format ("%s %s is currently being used, but outdated.%n" , fmtName , fmtVersion ));
202
239
builder .append (String .format ("%s %s is the recommended version, which may have fixed this problem.%n" , fmtName , recommendedFmtVersionOrNull ));
203
240
builder .append (String .format ("%s %s requires JVM %d+." , fmtName , recommendedFmtVersionOrNull , getRequiredJvmVersion (recommendedFmtVersionOrNull )));
204
241
} else {
205
- V higherFormatterVersionOrNull = fmt2jvmVersion .higherKey (fmtVersion );
242
+ V higherFormatterVersionOrNull = fmtMaxVersion2jvmVersion .higherKey (fmtVersion );
206
243
if (null != higherFormatterVersionOrNull ) {
207
244
builder .append (buildUpgradeJvmMessage (fmtVersion ));
208
- Integer higherJvmVersion = fmt2jvmVersion .get (higherFormatterVersionOrNull );
245
+ Integer higherJvmVersion = fmtMaxVersion2jvmVersion .get (higherFormatterVersionOrNull );
209
246
builder .append (String .format ("If you upgrade your JVM to %d+, then you can use %s %s, which may have fixed this problem." , higherJvmVersion , fmtName , higherFormatterVersionOrNull ));
210
247
}
211
248
}
@@ -215,7 +252,7 @@ private String buildUpgradeFormatterMessage(V fmtVersion) {
215
252
@ Override
216
253
public String toString () {
217
254
return String .format ("%s alternatives:%n" , fmtName ) +
218
- jvm2fmtVersion .entrySet ().stream ().map (
255
+ jvm2fmtMaxVersion .entrySet ().stream ().map (
219
256
e -> String .format ("- Version %s requires JVM %d+" , e .getValue (), e .getKey ())).collect (Collectors .joining (System .lineSeparator ()));
220
257
}
221
258
0 commit comments