public JCNewClass build() {
    // Generate a subclass of Callable
    ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
    int numParams = paramLists.getParameters().size();
    int minimumParams = 0;
    for (Parameter p : paramLists.getParameters()) {
      if (p.isDefaulted() || p.isSequenced()) break;
      minimumParams++;
    }
    boolean isVariadic = minimumParams != numParams;
    if (parameterListTree != null) {
      // generate a method for each defaulted param
      for (Tree.Parameter p : parameterListTree.getParameters()) {
        if (p.getDefaultArgument() != null || p.getDeclarationModel().isSequenced()) {
          MethodDefinitionBuilder methodBuilder =
              gen.classGen().makeParamDefaultValueMethod(false, null, parameterListTree, p);
          classBody.append(methodBuilder.build());
        }
      }
    }

    // collect each parameter type from the callable type model rather than the declarations to get
    // them all bound
    java.util.List<ProducedType> parameterTypes = new ArrayList<ProducedType>(numParams);
    if (forwardCallTo != null) {
      for (int i = 0; i < numParams; i++)
        parameterTypes.add(gen.getParameterTypeOfCallable(typeModel, i));
    } else {
      // get them from our declaration
      for (Parameter p : paramLists.getParameters()) parameterTypes.add(p.getType());
    }

    // now generate a method for each supported minimum number of parameters below 4
    // which delegates to the $call$typed method if required
    for (int i = minimumParams, max = Math.min(numParams, 4); i < max; i++) {
      classBody.append(makeDefaultedCall(i, isVariadic, parameterTypes));
    }
    // generate the $call method for the max number of parameters,
    // which delegates to the $call$typed method if required
    classBody.append(makeDefaultedCall(numParams, isVariadic, parameterTypes));
    // generate the $call$typed method if required
    if (isVariadic && forwardCallTo == null)
      classBody.append(makeCallTypedMethod(body, parameterTypes));

    JCClassDecl classDef =
        gen.make().AnonymousClassDef(gen.make().Modifiers(0), classBody.toList());

    JCNewClass instance =
        gen.make()
            .NewClass(
                null,
                null,
                gen.makeJavaType(typeModel, JT_EXTENDS | JT_CLASS_NEW),
                List.<JCExpression>of(gen.make().Literal(typeModel.getProducedTypeName(true))),
                classDef);
    return instance;
  }
Beispiel #2
0
 public String getProducedTypeName(boolean abbreviate) {
   if (getDeclaration() == null) {
     // unknown type
     return null;
   }
   if (abbreviate && getDeclaration() instanceof UnionType) {
     UnionType ut = (UnionType) getDeclaration();
     if (ut.getCaseTypes().size() == 2) {
       Unit unit = getDeclaration().getUnit();
       if (Util.isElementOfUnion(ut, unit.getNothingDeclaration())) {
         return unit.getDefiniteType(this).getProducedTypeName() + "?";
       }
       if (Util.isElementOfUnion(ut, unit.getEmptyDeclaration())
           && Util.isElementOfUnion(ut, unit.getSequenceDeclaration())) {
         return unit.getElementType(this).getProducedTypeName() + "[]";
       }
     }
   }
   String producedTypeName = "";
   if (getDeclaration().isMember()) {
     producedTypeName += getQualifyingType().getProducedTypeName(abbreviate);
     producedTypeName += ".";
   }
   producedTypeName += getDeclaration().getName();
   if (!getTypeArgumentList().isEmpty()) {
     producedTypeName += "<";
     for (ProducedType t : getTypeArgumentList()) {
       if (t == null) {
         producedTypeName += "unknown,";
       } else {
         producedTypeName += t.getProducedTypeName(abbreviate) + ",";
       }
     }
     producedTypeName += ">";
     producedTypeName = producedTypeName.replace(",>", ">");
   }
   return producedTypeName;
 }
 private static String type(Tree.Type type) {
   if (type == null) {
     return "<Unknown>";
   } else {
     ProducedType tm = type.getTypeModel();
     if (tm == null) {
       return "<Unknown>";
     } else {
       boolean sequenced = type instanceof Tree.SequencedType;
       if (sequenced) {
         tm = type.getUnit().getIteratedType(tm);
         if (tm == null) {
           return "<Unknown>";
         }
       }
       String tn = tm.getProducedTypeName();
       if (sequenced) {
         tn += "...";
       }
       return tn;
     }
   }
 }
  private void extractStatementsInFile(TextChange tfc) throws CoreException {
    tfc.setEdit(new MultiTextEdit());
    IDocument doc = tfc.getCurrentDocument(null);

    Tree.Body body = (Tree.Body) node;

    Integer start = statements.get(0).getStartIndex();
    int length = statements.get(statements.size() - 1).getStopIndex() - start + 1;
    FindContainerVisitor fsv = new FindContainerVisitor(body);
    rootNode.visit(fsv);
    Tree.Declaration decNode = fsv.getDeclaration();
    /*if (decNode instanceof Tree.Declaration) {
        Tree.AnnotationList anns = ((Tree.Declaration) decNode).getAnnotationList();
        if (anns!=null && !anns.getAnnotations().isEmpty()) {
            decNode = anns.getAnnotations().get(0);
        }
    }*/
    Declaration dec = decNode.getDeclarationModel();
    FindLocalReferencesVisitor flrv = new FindLocalReferencesVisitor(dec);
    for (Statement s : statements) {
      s.visit(flrv);
    }
    List<TypeDeclaration> localTypes = new ArrayList<TypeDeclaration>();
    List<Tree.BaseMemberExpression> localRefs = new ArrayList<Tree.BaseMemberExpression>();
    for (Tree.BaseMemberExpression bme : flrv.getLocalReferences()) {
      if (result == null || !bme.getDeclaration().equals(result.getDeclarationModel())) {
        FindOuterReferencesVisitor v = new FindOuterReferencesVisitor(bme.getDeclaration());
        for (Statement s : body.getStatements()) {
          if (!statements.contains(s)) {
            s.visit(v);
          }
        }
        if (v.refs > 0) {
          addLocalType(dec, bme.getTypeModel(), localTypes, new ArrayList<ProducedType>());
          localRefs.add(bme);
        }
      }
    }

    String params = "";
    String args = "";
    Set<Declaration> done = new HashSet<Declaration>();
    boolean nonempty = false;
    for (Tree.BaseMemberExpression bme : localRefs) {
      if (done.add(bme.getDeclaration())) {
        params +=
            bme.getTypeModel().getProducedTypeName() + " " + bme.getIdentifier().getText() + ", ";
        args += bme.getIdentifier().getText() + ", ";
        nonempty = true;
      }
    }
    if (nonempty) {
      params = params.substring(0, params.length() - 2);
      args = args.substring(0, args.length() - 2);
    }

    String indent = "\n" + getIndent(decNode, doc);
    String extraIndent = indent + getDefaultIndent();

    String typeParams = "";
    String constraints = "";
    if (!localTypes.isEmpty()) {
      for (TypeDeclaration t : localTypes) {
        typeParams += t.getName() + ", ";
        if (!t.getSatisfiedTypes().isEmpty()) {
          constraints += extraIndent + getDefaultIndent() + "given " + t.getName() + " satisfies ";
          for (ProducedType pt : t.getSatisfiedTypes()) {
            constraints += pt.getProducedTypeName() + "&";
          }
          constraints = constraints.substring(0, constraints.length() - 1);
        }
      }
      typeParams = "<" + typeParams.substring(0, typeParams.length() - 2) + ">";
    }

    String content =
        result == null ? "void" : result.getDeclarationModel().getType().getProducedTypeName();
    content += " " + newName + typeParams + "(" + params + ")" + constraints + " {";
    for (Statement s : statements) {
      content += extraIndent + toString(s);
    }
    if (result != null) {
      content += extraIndent + "return " + result.getDeclarationModel().getName() + ";";
    }
    content += indent + "}" + indent + indent;

    String invocation = newName + "(" + args + ");";
    if (result != null) {
      String modifs;
      if (result.getDeclarationModel().isShared()) {
        modifs = "shared " + result.getDeclarationModel().getType().getProducedTypeName() + " ";
      } else {
        modifs = "value ";
      }
      invocation = modifs + result.getDeclarationModel().getName() + "=" + invocation;
    }

    tfc.addEdit(new InsertEdit(decNode.getStartIndex(), content));
    tfc.addEdit(new ReplaceEdit(start, length, invocation));
  }
  private void extractExpressionInFile(TextChange tfc) throws CoreException {
    tfc.setEdit(new MultiTextEdit());
    IDocument doc = tfc.getCurrentDocument(null);

    Tree.Term term = (Tree.Term) node;
    Integer start = term.getStartIndex();
    int length = term.getStopIndex() - start + 1;
    String exp = toString(term);
    FindContainerVisitor fsv = new FindContainerVisitor(term);
    rootNode.visit(fsv);
    Tree.Declaration decNode = fsv.getDeclaration();
    /*if (decNode instanceof Tree.Declaration) {
    	Tree.AnnotationList anns = ((Tree.Declaration) decNode).getAnnotationList();
    	if (anns!=null && !anns.getAnnotations().isEmpty()) {
    		decNode = anns.getAnnotations().get(0);
    	}
    }*/
    Declaration dec = decNode.getDeclarationModel();
    FindLocalReferencesVisitor flrv = new FindLocalReferencesVisitor(dec);
    term.visit(flrv);
    List<TypeDeclaration> localTypes = new ArrayList<TypeDeclaration>();
    for (Tree.BaseMemberExpression bme : flrv.getLocalReferences()) {
      addLocalType(dec, bme.getTypeModel(), localTypes, new ArrayList<ProducedType>());
    }

    String params = "";
    String args = "";
    if (!flrv.getLocalReferences().isEmpty()) {
      for (Tree.BaseMemberExpression bme : flrv.getLocalReferences()) {
        params +=
            bme.getTypeModel().getProducedTypeName() + " " + bme.getIdentifier().getText() + ", ";
        args += bme.getIdentifier().getText() + ", ";
      }
      params = params.substring(0, params.length() - 2);
      args = args.substring(0, args.length() - 2);
    }

    String indent = "\n" + getIndent(decNode, doc);
    String extraIndent = indent + getDefaultIndent();

    String typeParams = "";
    String constraints = "";
    if (!localTypes.isEmpty()) {
      for (TypeDeclaration t : localTypes) {
        typeParams += t.getName() + ", ";
        if (!t.getSatisfiedTypes().isEmpty()) {
          constraints += extraIndent + getDefaultIndent() + "given " + t.getName() + " satisfies ";
          for (ProducedType pt : t.getSatisfiedTypes()) {
            constraints += pt.getProducedTypeName() + "&";
          }
          constraints = constraints.substring(0, constraints.length() - 1);
        }
      }
      typeParams = "<" + typeParams.substring(0, typeParams.length() - 2) + ">";
    }

    String type;
    String ending;
    if ("Void".equals(term.getTypeModel().getProducedTypeName())) {
      type = "void";
      ending = "";
    } else {
      type =
          explicitType || dec.isToplevel() ? term.getTypeModel().getProducedTypeName() : "function";
      ending = "return ";
    }

    tfc.addEdit(
        new InsertEdit(
            decNode.getStartIndex(),
            type
                + " "
                + newName
                + typeParams
                + "("
                + params
                + ")"
                + constraints
                + " {"
                + extraIndent
                + ending
                + exp
                + ";"
                + indent
                + "}"
                + indent
                + indent));
    tfc.addEdit(new ReplaceEdit(start, length, newName + "(" + args + ")"));
  }