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; }
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 + ")")); }