public static Pair<Map<String, String>, GroovyFile> externalParameters(String text, @NotNull final PsiElement context) {
    final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject());
    final GroovyFile toEval = factory.createGroovyFile(text, false, context);

    final GrFunctionalExpression functionalExpression = PsiTreeUtil.getParentOfType(context, GrFunctionalExpression.class);
    final Map<String, String> parameters = new HashMap<>();
    final Map<GrExpression, String> replacements = new HashMap<>();
    toEval.accept(new GroovyRecursiveElementVisitor() {
      @Override
      public void visitReferenceExpression(@NotNull GrReferenceExpression referenceExpression) {
        super.visitReferenceExpression(referenceExpression);

        if (PsiUtil.isThisReference(referenceExpression) || PsiUtil.isSuperReference(referenceExpression)) {
          replaceWithReference(referenceExpression, "delegate");
          return;
        }

        PsiElement resolved = referenceExpression.resolve();
        if (resolved instanceof PsiMember
            && (resolved instanceof PsiClass || ((PsiMember)resolved).hasModifierProperty(PsiModifier.STATIC))) {
          String qName = com.intellij.psi.util.PsiUtil.getMemberQualifiedName((PsiMember)resolved);
          if (qName != null && qName.contains(".") && !referenceExpression.isQualified()) {
            replaceWithReference(referenceExpression, qName);
            return;
          }
        }

        if (shouldDelegate(referenceExpression, resolved)) {
          replaceWithReference(referenceExpression, "delegate." + referenceExpression.getReferenceName());
          return;
        }

        if (resolved instanceof GrVariable && !(resolved instanceof GrField) && !PsiTreeUtil.isAncestor(toEval, resolved, false)) {
          final String name = ((GrVariable)resolved).getName();
          if (resolved instanceof ClosureSyntheticParameter
              && PsiTreeUtil.isAncestor(toEval, ((ClosureSyntheticParameter)resolved).getClosure(), false)) {
            return;
          }

          if (resolved instanceof GrBindingVariable && !PsiTreeUtil.isAncestor(resolved.getContainingFile(), toEval, false)) {
            return;
          }

          String value;
          if (functionalExpression != null &&
              !PsiTreeUtil.isAncestor(functionalExpression, resolved, false) &&
              !(resolved instanceof ClosureSyntheticParameter)) {
            // Evaluating inside functionalExpression for outer variable definitions
            // All non-local variables are accessed by references
            value = "this." + name;
          }
          else {
            value = name;
          }
          parameters.put(name, value);
          return;
        }

        if (resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter && !(resolved instanceof GrParameter)) {
          String name = referenceExpression.getReferenceName();
          parameters.put(name, name);
        }
      }

      private boolean shouldDelegate(GrReferenceExpression referenceExpression, @Nullable PsiElement resolved) {
        if (referenceExpression.isQualified()) {
          return false;
        }

        if (resolved instanceof GrField) {
          return true;
        }

        if (resolved instanceof PsiMethod) {
          String methodName = ((PsiMethod)resolved).getName();
          return functionalExpression != null &&
                 ("getDelegate".equals(methodName) || "getOwner".equals(methodName)) || "call".equals(methodName);
        }

        return false;
      }

      private void replaceWithReference(GrExpression expr, final String exprText) {
        replacements.put(expr, exprText);
      }

      @Override
      public void visitCodeReferenceElement(@NotNull GrCodeReferenceElement refElement) {
        super.visitCodeReferenceElement(refElement);
        if (refElement.getQualifier() == null) {
          PsiElement resolved = refElement.resolve();
          if (resolved instanceof PsiClass) {
            String qName = ((PsiClass)resolved).getQualifiedName();
            if (qName != null) {
              int dotIndex = qName.lastIndexOf(".");
              if (dotIndex < 0) return;
              String packageName = qName.substring(0, dotIndex);
              refElement.setQualifier(factory.createCodeReference(packageName));
            }
          }
        }
      }
    });

    for (GrExpression expression : replacements.keySet()) {
      expression.replaceWithExpression(factory.createExpressionFromText(replacements.get(expression)), false);
    }

    return Pair.create(parameters, toEval);
  }
public static Pair<Map<String, String>, GroovyFile> externalParameters(String text, @NotNull final PsiElement context)