Skip to content

Commit 2d47812

Browse files
committed
Attempting to improve the JShell behavior w.r.t. ELVD; test by biboudis.
1 parent d3f5b23 commit 2d47812

10 files changed

Lines changed: 218 additions & 34 deletions

File tree

src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,7 +3104,11 @@ private boolean cmdList(String arg) {
31043104
cmdout.println();
31053105
hasOutput[0] = true;
31063106
}
3107-
cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n "));
3107+
if (sn.subKind() == Snippet.SubKind.VAR_BINDING_SUBKIND) {
3108+
cmdout.printf("%4s : %s\n", sn.id(), messageFormat("jshell.msg.list.binding", ((VarSnippet) sn).name(), sn.source().replace("\n", "\n ")));
3109+
} else {
3110+
cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n "));
3111+
}
31083112
});
31093113
return true;
31103114
}
@@ -3965,7 +3969,7 @@ private void displayDeclarationAndValue() {
39653969
custom(FormatCase.VARDECL, vk.name(), vk.typeName());
39663970
break;
39673971
}
3968-
case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: {
3972+
case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, VAR_BINDING_SUBKIND: {
39693973
VarSnippet vk = (VarSnippet) sn;
39703974
custom(FormatCase.VARINIT, vk.name(), vk.typeName());
39713975
break;

src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ jshell.console.erroneous = \nIncomplete or erroneous. A single valid expression
194194
jshell.console.exprstmt = \nA single valid expression or statement must precede Shift+Tab m.
195195
jshell.console.empty = \nEmpty entry. A single valid expression or statement must precede Shift+Tab m.
196196

197+
#{0}: the name of the binding
198+
#{1}: the full snippet
199+
jshell.msg.list.binding = binding {0} in {1}
200+
197201
jshell.fix.wrong.shortcut =\
198202
Unexpected character after Shift+Tab.\n\
199203
Use "i" for auto-import, "v" for variable creation, or "m" for method creation.\n\

src/jdk.jshell/share/classes/jdk/jshell/Eval.java

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,6 @@ private List<Snippet> processEnhancedVarDecl(String userSource, Tree unitTree, S
266266
// short circuit since inference is expensive
267267
boolean hasAnyVars = false;
268268
for (JCTree.JCBindingPattern bp : patternBindings) {
269-
String bindingName = bp.getVariable().getName().toString();
270269
Tree bindingTypeTree = bp.getVariable().getType();
271270
if (bindingTypeTree.getKind() == Tree.Kind.VAR_TYPE) {
272271
hasAnyVars = true;
@@ -289,31 +288,49 @@ private List<Snippet> processEnhancedVarDecl(String userSource, Tree unitTree, S
289288
bindings = ExpressionToTypeInfo.enhancedLocalVariableDeclInferBindings(userSource, state, false);
290289
}
291290

292-
Wrap guts = Wrap.enhancedLocalVariableDeclWrap(compileSource, bindings);
293-
DiagList dl = trialCompile(guts);
291+
if (bindings.isEmpty()) {
292+
Wrap guts = Wrap.simpleWrap(compileSource);
293+
return List.of(new StatementSnippet(state.keyMap.keyForStatement(), userSource, guts));
294+
}
295+
296+
List<Snippet> result = new ArrayList<>();
297+
298+
Wrap primaryGuts = Wrap.primaryEnhancedLocalVariableDeclWrap(compileSource, bindings);
299+
DiagList dl = trialCompile(primaryGuts);
294300
if (dl.hasErrors()){
295301
return compileFailResult(dl, userSource, kindOfTree(unitTree));
296302
}
297303
TreeDependencyScanner tds = new TreeDependencyScanner();
298304
tds.scan(unitTree);
299305

300-
BindingInfo primary = bindings.getFirst();
301-
Set<String> additionalStaticImportNames =
302-
bindings.stream().skip(1).map(BindingInfo::bindingName).collect(Collectors.toSet());
306+
BindingInfo primaryBinding = bindings.getFirst();
303307

304-
Snippet snip = new VarSnippet(
305-
state.keyMap.keyForVariable((primary.bindingName())),
308+
VarSnippet primarySnippet = new VarSnippet(
309+
state.keyMap.keyForVariable((primaryBinding.bindingName())),
306310
userSource,
307-
guts,
308-
primary.bindingName(),
309-
primary.bindingName(),
310-
SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND,
311-
primary.displayTypeName(),
312-
primary.hasEnhancedType() ? primary.fullTypeName() : null,
313-
additionalStaticImportNames,
314-
tds.declareReferences(), null);
315-
316-
return singletonList(snip);
311+
primaryGuts,
312+
primaryBinding.bindingName(),
313+
primaryBinding.bindingName(),
314+
SubKind.VAR_BINDING_SUBKIND,
315+
primaryBinding.displayTypeName(),
316+
primaryBinding.hasEnhancedType() ? primaryBinding.fullTypeName() : null,
317+
Set.of(),
318+
tds.declareReferences(), null, List.of());
319+
result.add(primarySnippet);
320+
bindings.stream().skip(1).map(bi -> new VarSnippet(
321+
state.keyMap.keyForVariable((bi.bindingName())),
322+
userSource,
323+
Wrap.secondaryEnhancedLocalVariableDeclWrap(compileSource, bi),
324+
bi.bindingName(),
325+
bi.bindingName(),
326+
SubKind.VAR_BINDING_SUBKIND,
327+
bi.displayTypeName(),
328+
bi.hasEnhancedType() ? bi.fullTypeName() : null,
329+
Set.of(),
330+
tds.declareReferences(), null, List.of(new Snippet.ExtraImport(primarySnippet, bi.bindingName()))))
331+
.forEach(result::add);
332+
333+
return result;
317334
}
318335
// where
319336
static void gatherBindings(JCTree pattern, Consumer<JCTree.JCBindingPattern> sink) {
@@ -505,7 +522,7 @@ private List<Snippet> processVariables(String userSource, List<? extends Tree> u
505522
DiagList modDiag = modifierDiagnostics(vt.getModifiers(), dis, true);
506523
Snippet snip = new VarSnippet(state.keyMap.keyForVariable(name), userSource, guts,
507524
name, fieldName, subkind, displayType, hasEnhancedType ? fullTypeName : null, additionalStaticImportNames,
508-
tds.declareReferences(), modDiag);
525+
tds.declareReferences(), modDiag, List.of());
509526
snippets.add(snip);
510527
}
511528
return snippets;
@@ -766,7 +783,7 @@ private List<Snippet> processExpression(String userSource, Tree tree, String com
766783
Collection<String> declareReferences = null; //TODO
767784
snip = new VarSnippet(state.keyMap.keyForVariable(name), userSource, guts,
768785
name, name, SubKind.TEMP_VAR_EXPRESSION_SUBKIND, displayTypeName, fullTypeName,
769-
additionalStaticImportNames, declareReferences, null);
786+
additionalStaticImportNames, declareReferences, null, List.of());
770787
} else {
771788
guts = Wrap.methodReturnWrap(compileSource);
772789
snip = new ExpressionSnippet(state.keyMap.keyForExpression(name, typeName), userSource, guts,

src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,14 @@ private CompoundWrap wrappedInClass(String className, String imports, List<Wrap>
7171
return new CompoundWrap(elems.toArray());
7272
}
7373

74-
OuterWrap wrapInClass(Set<Key> except, Collection<Snippet> plus,
74+
OuterWrap wrapInClass(Set<Key> except, Collection<Snippet> plus, List<String> additionalExtraImports,
7575
List<Snippet> snippets, List<Wrap> wraps) {
7676
List<String> extraImports =
7777
plus.stream()
7878
.map(psi -> psi.importLine(state))
7979
.toList();
80-
String imports = state.maps.packageAndImportsExcept(except, extraImports);
80+
String imports = state.maps.packageAndImportsExcept(except, extraImports) +
81+
additionalExtraImports.stream().collect(Collectors.joining("\n", "\n", ""));
8182
// className is unique to the set of snippets and their version (seq)
8283
String className = REPL_CLASS_PREFIX + snippets.stream()
8384
.sorted((sn1, sn2) -> sn1.key().index() - sn2.key().index())

src/jdk.jshell/share/classes/jdk/jshell/Snippet.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,13 @@ public enum SubKind {
279279
*/
280280
VAR_DECLARATION_WITH_INITIALIZER_SUBKIND(Kind.VAR, true, true),
281281

282+
/**
283+
* An binding variable.
284+
* {@code SubKind} of {@link Kind#VAR}.
285+
* @since 27
286+
*/
287+
VAR_BINDING_SUBKIND(Kind.VAR, true, true),
288+
282289
/**
283290
* An expression whose value has been stored in a temporary variable. A
284291
* {@code SubKind} of {@link Kind#VAR}.
@@ -768,4 +775,9 @@ boolean isExecutable() {
768775
return subkind.isExecutable();
769776
}
770777

778+
List<ExtraImport> getExtraImports() {
779+
return List.of();
780+
}
781+
782+
record ExtraImport(Snippet from, String name) {}
771783
}

src/jdk.jshell/share/classes/jdk/jshell/Unit.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ void setWrap(Collection<Unit> exceptUnit, Collection<Unit> plusUnfiltered) {
179179
.map(u -> u.activeGuts)
180180
.toList();
181181
// Set the outer wrap for this snippet
182-
si.setOuterWrap(state.outerMap.wrapInClass(except, plus, snippets, wraps));
182+
List<String> additionalExtraImports = units.stream().flatMap(u -> u.snippet().getExtraImports().stream())
183+
.map(ei -> "import static " + ei.from().classFullName() + "." + ei.name() + "_;")
184+
.toList();
185+
si.setOuterWrap(state.outerMap.wrapInClass(except, plus, additionalExtraImports, snippets, wraps));
183186
state.debug(DBG_WRAP, "++setWrap() %s\n%s\n",
184187
si, si.outerWrap().wrapped());
185188
}

src/jdk.jshell/share/classes/jdk/jshell/VarSnippet.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package jdk.jshell;
2727

2828
import java.util.Collection;
29+
import java.util.List;
2930
import java.util.Set;
3031
import jdk.jshell.Key.VarKey;
3132

@@ -61,16 +62,19 @@ public class VarSnippet extends DeclarationSnippet {
6162

6263
final String fieldName;
6364

65+
private final List<ExtraImport> extraImports;
66+
6467
VarSnippet(VarKey key, String userSource, Wrap guts,
6568
String name, String fieldName, SubKind subkind, String typeName, String fullTypeName,
6669
Set<String> additionalStaticImportNames, Collection<String> declareReferences,
67-
DiagList syntheticDiags) {
70+
DiagList syntheticDiags, List<ExtraImport> extraImports) {
6871
super(key, userSource, guts, name, subkind, null, declareReferences,
6972
null, syntheticDiags);
7073
this.typeName = typeName;
7174
this.fullTypeName = fullTypeName;
7275
this.additionalStaticImportNames = additionalStaticImportNames;
7376
this.fieldName = fieldName;
77+
this.extraImports = extraImports;
7478
}
7579

7680
String fieldName() {
@@ -92,4 +96,9 @@ String importLine(JShell state) {
9296
return imports.toString();
9397
}
9498

99+
@Override
100+
List<ExtraImport> getExtraImports() {
101+
return extraImports;
102+
}
103+
95104
}

src/jdk.jshell/share/classes/jdk/jshell/Wrap.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,17 @@ private static int countLines(String s, int from, int toEx) {
184184
return cnt;
185185
}
186186

187-
public static Wrap enhancedLocalVariableDeclWrap(String compileSource, List<BindingInfo> bindings) {
187+
public static Wrap primaryEnhancedLocalVariableDeclWrap(String compileSource, List<BindingInfo> bindings) {
188188
List<Wrap> members = new ArrayList<>();
189189
List<String> methodsForAssigningBindings = new ArrayList<>(bindings.size());
190190

191191
// public static Type bindingName;
192+
String suffix = "";
192193
for (var b : bindings) {
193194
members.add(new CompoundWrap(
194-
" public static\n ", b.declareTypeName(), " ", b.bindingName(), ";\n"
195+
" public static\n ", b.declareTypeName(), " ", b.bindingName() + suffix, ";\n"
195196
));
197+
suffix = "_";
196198
}
197199

198200
// public static Type $setBindingMethodName(Type $v) { return bindingName = $v; }
@@ -202,8 +204,8 @@ public static Wrap enhancedLocalVariableDeclWrap(String compileSource, List<Bind
202204
String methodName = setBindingMethodName + "$" + i;
203205
methodsForAssigningBindings.add(methodName);
204206
members.add(new CompoundWrap(
205-
" private static ", bi.declareTypeName(), " ", methodName, "(", bi.declareTypeName(), " $v", ") { \n",
206-
" return ", bi.bindingName(), " = $v", ";\n",
207+
" private static ", bi.declareTypeName(), " ", methodName, "(", bi.declareTypeName(), " " + bi.bindingName() + "__", ") { \n",
208+
" return ", bi.bindingName() + (i == 0 ? "" : "_"), " = " + bi.bindingName() + "__", ";\n",
207209
"}\n"));
208210
}
209211

@@ -228,6 +230,19 @@ public static Wrap enhancedLocalVariableDeclWrap(String compileSource, List<Bind
228230
return new CompoundWrap(members.toArray());
229231
}
230232

233+
public static Wrap secondaryEnhancedLocalVariableDeclWrap(String compileSource, BindingInfo binding) {
234+
List<Wrap> members = new ArrayList<>();
235+
236+
// public static Type bindingName;
237+
members.add(new CompoundWrap(
238+
" public static\n ", binding.declareTypeName(), " ", binding.bindingName(), ";\n"
239+
));
240+
241+
members.add(new DoitMethodWrap(new CompoundWrap(" return " + binding.bindingName() + " = " + binding.bindingName() + "_;")));
242+
243+
return new CompoundWrap(members.toArray());
244+
}
245+
231246
public static final class Range {
232247
final int begin;
233248
final int end; // exclusive

0 commit comments

Comments
 (0)