JavaCodeFragment (TextWithImports textWithImports, PsiElement context, Project project) { final Pair<Map<String, String>, GroovyFile> pair = externalParameters(textWithImports.getText(), context); GroovyFile toEval = pair.second; final Map<String, String> parameters = pair.first; List<String> names = new ArrayList<>(parameters.keySet()); List<String> values = ContainerUtil.map(names, name -> parameters.get(name)); String text = toEval.getText(); final String groovyText = StringUtil.join(names, ", ") + "->" + stripImports(text, toEval); PsiClass contextClass = PsiUtil.getContextClass(context); boolean isStatic = isStaticContext(context); StringBuilder javaText = new StringBuilder(); javaText.append("java.lang.Class |clazz;\n"); if (!isStatic) { javaText.append("java.lang.Object |thiz0;\n"); PsiFile containingFile = context.getContainingFile(); if (containingFile.getContext() != null) { containingFile = containingFile.getContext().getContainingFile(); } String fileName = containingFile.getOriginalFile().getName(); String s = StringUtil.escapeStringCharacters(Pattern.quote(fileName)); // We believe what class is reloaded if stacktrace matches one of two patterns: // 1.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), com.package.Foo$$DNLbVXwm.methodName(Unknown Source), * // 2.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), * com.springsource.loaded. * // Pattern below test this. //javaText.append("System.out.println(java.util.Arrays.toString(new Exception().getStackTrace()));\n"); //javaText.append("System.out.println(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(" + s + ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), |.+(?:com|org)\\\\.springsource\\\\.loaded\\\\.).+\")\n"); javaText.append("Class.forName(\"java.lang.StackTraceElement\");\n"); javaText.append("StackTraceElement[] |trace = new Exception().getStackTrace();\n"); javaText.append( "if (java.util.Arrays.toString(|trace).matches(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(") .append(s) .append( ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), $OR$.+(?:com$OR$org)\\\\.springsource\\\\.loaded\\\\.).+\")) {\n"); javaText.append(" |thiz0 = thiz;\n"); javaText.append(" } else {\n"); if (contextClass instanceof GrTraitTypeDefinition) { javaText.append(" |thiz0 = $self;\n"); } else { javaText.append(" |thiz0 = this;\n"); } javaText.append(" }\n"); } if (!isStatic) { javaText.append("|clazz = |thiz0.getClass();\n"); } else { assert contextClass != null; javaText.append("|clazz = java.lang.Class.forName(\"").append(ClassUtil.getJVMClassName(contextClass)).append("\");\n"); } javaText.append(""" final java.lang.ClassLoader |parentLoader = |clazz.getClassLoader(); final groovy.lang.GroovyClassLoader |loader = new groovy.lang.GroovyClassLoader(|parentLoader); final java.lang.Class |c = |loader.parseClass("""); javaText.append("\"" + IMPORTS + "class DUMMY").append(" { ").append("public groovy.lang.Closure ") .append(EVAL_NAME).append(" = {\\n").append(TEXT).append("\\n}}\""); javaText.append(""" , "DUMMY.groovy"); int |i; java.lang.reflect.Field[] |fields = |c.getFields(); for (int |j = 0; |j < |fields.length; |j++) if (|fields[|j].getName().equals("_JETGROOVY_EVAL_")) {|i = |j; break;} final java.lang.reflect.Field |field = |fields[|i]; final java.lang.Object |closure = |field.get(|c.newInstance()); """); javaText.append("groovy.lang.ExpandoMetaClass |emc = new groovy.lang.ExpandoMetaClass(|clazz);\n"); if (!isStatic) { javaText.append("|closure.setDelegate(|thiz0);\n"); javaText.append("|emc.setProperty(\"").append(EVAL_NAME).append("\", |closure);\n"); } else { javaText.append("|emc.getProperty(\"static\").setProperty(\"").append(EVAL_NAME).append("\", |closure);\n"); } javaText.append("|emc.initialize();\n"); javaText.append(unwrapVals(values)); if (!isStatic) { javaText.append( "java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeMethod(|thiz0, \"" ).append(EVAL_NAME).append("\", |resVals);\n"); } else { javaText.append( "java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeStaticMethod(|clazz, \"" ).append(EVAL_NAME).append("\", |resVals);\n"); } javaText.append("|res"); final PsiElementFactory factory = JavaPsiFacade.getInstance(toEval.getProject()).getElementFactory(); final String hiddenJavaVars = StringUtil.replace( javaText.toString(), "|", "_$_" + new Random().nextInt(42) ).replaceAll("\\$OR\\$", "|"); final String finalText = StringUtil.replace( StringUtil.replace(hiddenJavaVars, TEXT, groovyText), IMPORTS, textWithImports.getImports() ); final JavaCodeFragment result = JavaCodeFragmentFactory.getInstance(project).createCodeBlockCodeFragment(finalText, null, true); if (contextClass != null) { result.setThisType(factory.createType(contextClass)); } return result; }