src/jdk.jshell/share/classes/jdk/jshell/Eval.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 52775 d488477865c0
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
     1 /*
     1 /*
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    42 import com.sun.source.tree.MethodTree;
    42 import com.sun.source.tree.MethodTree;
    43 import com.sun.source.tree.ModifiersTree;
    43 import com.sun.source.tree.ModifiersTree;
    44 import com.sun.source.tree.NewClassTree;
    44 import com.sun.source.tree.NewClassTree;
    45 import com.sun.source.tree.Tree;
    45 import com.sun.source.tree.Tree;
    46 import com.sun.source.tree.VariableTree;
    46 import com.sun.source.tree.VariableTree;
    47 import com.sun.source.util.TreeScanner;
       
    48 import com.sun.tools.javac.tree.JCTree;
    47 import com.sun.tools.javac.tree.JCTree;
    49 import com.sun.tools.javac.tree.Pretty;
    48 import com.sun.tools.javac.tree.Pretty;
    50 import java.io.IOException;
    49 import java.io.IOException;
    51 import java.io.StringWriter;
    50 import java.io.StringWriter;
    52 import java.io.Writer;
    51 import java.io.Writer;
    96  * @author Robert Field
    95  * @author Robert Field
    97  */
    96  */
    98 class Eval {
    97 class Eval {
    99 
    98 
   100     private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\p{javaWhitespace}+(?<static>static\\p{javaWhitespace}+)?(?<fullname>[\\p{L}\\p{N}_\\$\\.]+\\.(?<name>[\\p{L}\\p{N}_\\$]+|\\*))");
    99     private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\p{javaWhitespace}+(?<static>static\\p{javaWhitespace}+)?(?<fullname>[\\p{L}\\p{N}_\\$\\.]+\\.(?<name>[\\p{L}\\p{N}_\\$]+|\\*))");
       
   100     private static final Pattern DEFAULT_PREFIX = Pattern.compile("\\p{javaWhitespace}*(default)\\p{javaWhitespace}+");
   101 
   101 
   102     // for uses that should not change state -- non-evaluations
   102     // for uses that should not change state -- non-evaluations
   103     private boolean preserveState = false;
   103     private boolean preserveState = false;
   104 
   104 
   105     private int varNumber = 0;
   105     private int varNumber = 0;
   199             if (units.isEmpty()) {
   199             if (units.isEmpty()) {
   200                 return compileFailResult(pt, userSource, Kind.ERRONEOUS);
   200                 return compileFailResult(pt, userSource, Kind.ERRONEOUS);
   201             }
   201             }
   202             Tree unitTree = units.get(0);
   202             Tree unitTree = units.get(0);
   203             if (pt.getDiagnostics().hasOtherThanNotStatementErrors()) {
   203             if (pt.getDiagnostics().hasOtherThanNotStatementErrors()) {
   204                 return compileFailResult(pt, userSource, kindOfTree(unitTree));
   204                 Matcher matcher = DEFAULT_PREFIX.matcher(compileSource);
       
   205                 DiagList dlist = matcher.lookingAt()
       
   206                         ? new DiagList(new ModifierDiagnostic(true,
       
   207                             state.messageFormat("jshell.diag.modifier.single.fatal", "'default'"),
       
   208                             matcher.start(1), matcher.end(1)))
       
   209                         : pt.getDiagnostics();
       
   210                 return compileFailResult(dlist, userSource, kindOfTree(unitTree));
   205             }
   211             }
   206 
   212 
   207             // Erase illegal/ignored modifiers
   213             // Erase illegal/ignored modifiers
   208             String compileSourceInt = new MaskCommentsAndModifiers(compileSource, true).cleared();
   214             String compileSourceInt = new MaskCommentsAndModifiers(compileSource, true).cleared();
   209 
   215 
   613                     }
   619                     }
   614                     while (name == null || state.keyMap.doesVariableNameExist(name)) {
   620                     while (name == null || state.keyMap.doesVariableNameExist(name)) {
   615                         name = "$" + ++varNumber;
   621                         name = "$" + ++varNumber;
   616                     }
   622                     }
   617                 }
   623                 }
   618                 TreeDissector dis = TreeDissector.createByFirstClass(pt);
       
   619                 ExpressionInfo varEI =
   624                 ExpressionInfo varEI =
   620                         ExpressionToTypeInfo.localVariableTypeForInitializer(compileSource, state, true);
   625                         ExpressionToTypeInfo.localVariableTypeForInitializer(compileSource, state, true);
   621                 String declareTypeName;
   626                 String declareTypeName;
   622                 String fullTypeName;
   627                 String fullTypeName;
   623                 String displayTypeName;
   628                 String displayTypeName;
   625                 if (varEI != null) {
   630                 if (varEI != null) {
   626                     declareTypeName = varEI.declareTypeName;
   631                     declareTypeName = varEI.declareTypeName;
   627                     fullTypeName = varEI.fullTypeName;
   632                     fullTypeName = varEI.fullTypeName;
   628                     displayTypeName = varEI.displayTypeName;
   633                     displayTypeName = varEI.displayTypeName;
   629 
   634 
       
   635                     TreeDissector dis = TreeDissector.createByFirstClass(pt);
   630                     Pair<Wrap, Wrap> anonymous2Member =
   636                     Pair<Wrap, Wrap> anonymous2Member =
   631                             anonymous2Member(varEI, compileSource, new Range(0, compileSource.length()), dis, expr.getExpression());
   637                             anonymous2Member(varEI, compileSource, new Range(0, compileSource.length()), dis, expr.getExpression());
   632                     guts = Wrap.tempVarWrap(anonymous2Member.second.wrapped(), declareTypeName, name, anonymous2Member.first);
   638                     guts = Wrap.tempVarWrap(anonymous2Member.second.wrapped(), declareTypeName, name, anonymous2Member.first);
   633                     anonymousClasses = varEI.anonymousClasses.stream().map(ad -> ad.declareTypeName).collect(Collectors.toSet());
   639                     anonymousClasses = varEI.anonymousClasses.stream().map(ad -> ad.declareTypeName).collect(Collectors.toSet());
   634                 } else {
   640                 } else {
   671 
   677 
   672         ClassTree klassTree = (ClassTree) unitTree;
   678         ClassTree klassTree = (ClassTree) unitTree;
   673         String name = klassTree.getSimpleName().toString();
   679         String name = klassTree.getSimpleName().toString();
   674         DiagList modDiag = modifierDiagnostics(klassTree.getModifiers(), dis, false);
   680         DiagList modDiag = modifierDiagnostics(klassTree.getModifiers(), dis, false);
   675         TypeDeclKey key = state.keyMap.keyForClass(name);
   681         TypeDeclKey key = state.keyMap.keyForClass(name);
   676         // Corralling mutates.  Must be last use of pt, unitTree, klassTree
   682         // Corralling
   677         Wrap corralled = new Corraller(key.index(), pt.getContext()).corralType(klassTree);
   683         Wrap corralled = new Corraller(dis, key.index(), compileSource).corralType(klassTree);
   678 
   684 
   679         Wrap guts = Wrap.classMemberWrap(compileSource);
   685         Wrap guts = Wrap.classMemberWrap(compileSource);
   680         Snippet snip = new TypeDeclSnippet(key, userSource, guts,
   686         Snippet snip = new TypeDeclSnippet(key, userSource, guts,
   681                 name, snippetKind,
   687                 name, snippetKind,
   682                 corralled, tds.declareReferences(), tds.bodyReferences(), modDiag);
   688                 corralled, tds.declareReferences(), tds.bodyReferences(), modDiag);
   743                 .map(param -> dis.treeToRange(param.getType()).part(compileSource))
   749                 .map(param -> dis.treeToRange(param.getType()).part(compileSource))
   744                 .collect(Collectors.joining(","));
   750                 .collect(Collectors.joining(","));
   745         Tree returnType = mt.getReturnType();
   751         Tree returnType = mt.getReturnType();
   746         DiagList modDiag = modifierDiagnostics(mt.getModifiers(), dis, true);
   752         DiagList modDiag = modifierDiagnostics(mt.getModifiers(), dis, true);
   747         MethodKey key = state.keyMap.keyForMethod(name, parameterTypes);
   753         MethodKey key = state.keyMap.keyForMethod(name, parameterTypes);
   748         // Corralling mutates.  Must be last use of pt, unitTree, mt
   754         // Corralling
   749         Wrap corralled = new Corraller(key.index(), pt.getContext()).corralMethod(mt);
   755         Wrap corralled = new Corraller(dis, key.index(), compileSource).corralMethod(mt);
   750 
   756 
   751         if (modDiag.hasErrors()) {
   757         if (modDiag.hasErrors()) {
   752             return compileFailResult(modDiag, userSource, Kind.METHOD);
   758             return compileFailResult(modDiag, userSource, Kind.METHOD);
   753         }
   759         }
   754         Wrap guts = Wrap.classMemberWrap(compileSource);
   760         Wrap guts = Wrap.classMemberWrap(compileSource);
   965             ins.stream().forEach(u -> u.setWrap(ins, ins));
   971             ins.stream().forEach(u -> u.setWrap(ins, ins));
   966             state.taskFactory.analyze(outerWrapSet(ins), at -> {
   972             state.taskFactory.analyze(outerWrapSet(ins), at -> {
   967                 ins.stream().forEach(u -> u.setDiagnostics(at));
   973                 ins.stream().forEach(u -> u.setDiagnostics(at));
   968 
   974 
   969                 // corral any Snippets that need it
   975                 // corral any Snippets that need it
   970                 if (ins.stream().anyMatch(u -> u.corralIfNeeded(ins))) {
   976                 if (ins.stream().filter(u -> u.corralIfNeeded(ins)).count() > 0) {
   971                     // if any were corralled, re-analyze everything
   977                     // if any were corralled, re-analyze everything
   972                     state.taskFactory.analyze(outerWrapSet(ins), cat -> {
   978                     state.taskFactory.analyze(outerWrapSet(ins), cat -> {
   973                         ins.stream().forEach(u -> u.setCorralledDiagnostics(cat));
   979                         ins.stream().forEach(u -> u.setCorralledDiagnostics(cat));
   974                         ins.stream().forEach(u -> u.setStatus(cat));
   980                         ins.stream().forEach(u -> u.setStatus(cat));
   975                         return null;
   981                         return null;
  1152                         String.join(" ", objectMethods));
  1158                         String.join(" ", objectMethods));
  1153             }
  1159             }
  1154         };
  1160         };
  1155     }
  1161     }
  1156 
  1162 
  1157     private DiagList modifierDiagnostics(ModifiersTree modtree,
  1163     private class ModifierDiagnostic extends Diag {
  1158             final TreeDissector dis, boolean isAbstractProhibited) {
       
  1159 
       
  1160         class ModifierDiagnostic extends Diag {
       
  1161 
  1164 
  1162             final boolean fatal;
  1165             final boolean fatal;
  1163             final String message;
  1166             final String message;
  1164             long start;
  1167             final long start;
  1165             long end;
  1168             final long end;
  1166 
  1169 
  1167             ModifierDiagnostic(List<Modifier> list, boolean fatal) {
  1170             ModifierDiagnostic(boolean fatal,
       
  1171                     final String message,
       
  1172                     long start,
       
  1173                     long end) {
  1168                 this.fatal = fatal;
  1174                 this.fatal = fatal;
  1169                 StringBuilder sb = new StringBuilder();
  1175                 this.message = message;
  1170                 for (Modifier mod : list) {
  1176                 this.start = start;
  1171                     sb.append("'");
  1177                 this.end = end;
  1172                     sb.append(mod.toString());
       
  1173                     sb.append("' ");
       
  1174                 }
       
  1175                 String key = (list.size() > 1)
       
  1176                         ? fatal
       
  1177                             ? "jshell.diag.modifier.plural.fatal"
       
  1178                             : "jshell.diag.modifier.plural.ignore"
       
  1179                         : fatal
       
  1180                             ? "jshell.diag.modifier.single.fatal"
       
  1181                             : "jshell.diag.modifier.single.ignore";
       
  1182                 this.message = state.messageFormat(key, sb.toString());
       
  1183                 start = dis.getStartPosition(modtree);
       
  1184                 end = dis.getEndPosition(modtree);
       
  1185             }
  1178             }
  1186 
  1179 
  1187             @Override
  1180             @Override
  1188             public boolean isError() {
  1181             public boolean isError() {
  1189                 return fatal;
  1182                 return fatal;
  1213 
  1206 
  1214             @Override
  1207             @Override
  1215             public String getMessage(Locale locale) {
  1208             public String getMessage(Locale locale) {
  1216                 return message;
  1209                 return message;
  1217             }
  1210             }
  1218         }
  1211     }
       
  1212 
       
  1213     private DiagList modifierDiagnostics(ModifiersTree modtree,
       
  1214                                          final TreeDissector dis, boolean isAbstractProhibited) {
  1219 
  1215 
  1220         List<Modifier> list = new ArrayList<>();
  1216         List<Modifier> list = new ArrayList<>();
  1221         boolean fatal = false;
  1217         boolean fatal = false;
  1222         for (Modifier mod : modtree.getFlags()) {
  1218         for (Modifier mod : modtree.getFlags()) {
  1223             switch (mod) {
  1219             switch (mod) {
  1241                 case FINAL:
  1237                 case FINAL:
  1242                     list.add(mod);
  1238                     list.add(mod);
  1243                     break;
  1239                     break;
  1244             }
  1240             }
  1245         }
  1241         }
  1246         return list.isEmpty()
  1242         if (list.isEmpty()) {
  1247                 ? new DiagList()
  1243             return new DiagList();
  1248                 : new DiagList(new ModifierDiagnostic(list, fatal));
  1244         } else {
       
  1245             StringBuilder sb = new StringBuilder();
       
  1246             for (Modifier mod : list) {
       
  1247                 sb.append("'");
       
  1248                 sb.append(mod.toString());
       
  1249                 sb.append("' ");
       
  1250             }
       
  1251             String key = (list.size() > 1)
       
  1252                     ? fatal
       
  1253                     ? "jshell.diag.modifier.plural.fatal"
       
  1254                     : "jshell.diag.modifier.plural.ignore"
       
  1255                     : fatal
       
  1256                     ? "jshell.diag.modifier.single.fatal"
       
  1257                     : "jshell.diag.modifier.single.ignore";
       
  1258             String message = state.messageFormat(key, sb.toString().trim());
       
  1259             return new DiagList(new ModifierDiagnostic(fatal, message,
       
  1260                     dis.getStartPosition(modtree), dis.getEndPosition(modtree)));
       
  1261         }
  1249     }
  1262     }
  1250 
  1263 
  1251     String computeDeclareName(TypeSymbol ts) {
  1264     String computeDeclareName(TypeSymbol ts) {
  1252         return Util.JSHELL_ANONYMOUS + "$" + Long.toUnsignedString(anonCount++);
  1265         return Util.JSHELL_ANONYMOUS + "$" + Long.toUnsignedString(anonCount++);
  1253     }
  1266     }