package com.redhat.ceylon.eclipse.code.complete; import static com.redhat.ceylon.eclipse.ui.CeylonResources.LOCAL_NAME; import static com.redhat.ceylon.eclipse.util.Nodes.addNameProposals; import static com.redhat.ceylon.model.typechecker.model.ModelUtil.isTypeUnknown; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.jface.text.contentassist.ICompletionProposal; import com.redhat.ceylon.compiler.typechecker.tree.Node; import com.redhat.ceylon.compiler.typechecker.tree.Tree; import com.redhat.ceylon.compiler.typechecker.tree.Visitor; import com.redhat.ceylon.eclipse.code.parse.CeylonParseController; import com.redhat.ceylon.ide.common.util.escaping_; import com.redhat.ceylon.model.typechecker.model.Type; import com.redhat.ceylon.model.typechecker.model.Unit; @Deprecated public class MemberNameCompletions { static void addMemberNameProposals(final int offset, final CeylonParseController controller, final Node node, final List<ICompletionProposal> result) { final Integer startIndex2 = node.getStartIndex(); final Tree.CompilationUnit upToDateAndTypechecked = controller.getTypecheckedRootNode(); if (upToDateAndTypechecked != null) { new Visitor() { @Override public void visit( Tree.StaticMemberOrTypeExpression that) { Tree.TypeArguments tal = that.getTypeArguments(); Integer startIndex = tal==null ? null : tal.getStartIndex(); if (startIndex!=null && startIndex2!=null && startIndex.intValue()==startIndex2.intValue()) { addMemberNameProposal(offset, "", that, result, upToDateAndTypechecked); } super.visit(that); } @Override public void visit( Tree.SimpleType that) { Tree.TypeArgumentList tal = that.getTypeArgumentList(); Integer startIndex = tal==null ? null : tal.getStartIndex(); if (startIndex!=null && startIndex2!=null && startIndex.intValue()==startIndex2.intValue()) { addMemberNameProposal(offset, "", that, result, upToDateAndTypechecked); } super.visit(that); } }.visit(upToDateAndTypechecked); } } static void addMemberNameProposal(int offset, String prefix, final Node previousNode, List<ICompletionProposal> result, Tree.CompilationUnit rootNode) { class FindCompoundTypeVisitor extends Visitor { Node result = previousNode; @Override public void visit(Tree.Type that) { if (that.getStartIndex()<=previousNode.getStartIndex() && that.getEndIndex()>=previousNode.getEndIndex()) { result = that; } } } FindCompoundTypeVisitor fcv = new FindCompoundTypeVisitor(); fcv.visit(rootNode); Node node = fcv.result; Set<String> proposals = new LinkedHashSet<String>(); if (node instanceof Tree.TypeDeclaration) { //TODO: dictionary completions? return; } else if (node instanceof Tree.TypedDeclaration) { Tree.TypedDeclaration td = (Tree.TypedDeclaration) node; Tree.Type type = td.getType(); Tree.Identifier id = td.getIdentifier(); if (id==null || offset>=id.getStartIndex() && offset<=id.getEndIndex()) { node = type; } else { node = null; } } addProposalsForType(node, proposals); /*if (suggestedName!=null) { suggestedName = lower(suggestedName); String unquoted = prefix.startsWith("\\i")||prefix.startsWith("\\I") ? prefix.substring(2) : prefix; if (!suggestedName.startsWith(unquoted)) { suggestedName = prefix + upper(suggestedName); } result.add(new CompletionProposal(offset, prefix, LOCAL_NAME, suggestedName, escape(suggestedName))); }*/ /*if (proposals.isEmpty()) { proposals.add("it"); }*/ for (String name: proposals) { String unquotedPrefix = prefix.startsWith("\\i") ? prefix.substring(2) : prefix; if (name.startsWith(unquotedPrefix)) { String unquotedName = name.startsWith("\\i") ? name.substring(2) : name; result.add(new CompletionProposal(offset, prefix, LOCAL_NAME, unquotedName, name)); } } } public static void addProposalsForType(Node node, Set<String> proposals) { if (node instanceof Tree.SimpleType) { Tree.SimpleType simpleType = (Tree.SimpleType) node; addProposals(proposals, simpleType.getIdentifier(), simpleType.getTypeModel()); } else if (node instanceof Tree.BaseTypeExpression) { Tree.BaseTypeExpression typeExpression = (Tree.BaseTypeExpression) node; addProposals(proposals, typeExpression.getIdentifier(), getLiteralType(node, typeExpression)); } else if (node instanceof Tree.QualifiedTypeExpression) { Tree.QualifiedTypeExpression typeExpression = (Tree.QualifiedTypeExpression) node; addProposals(proposals, typeExpression.getIdentifier(), getLiteralType(node, typeExpression)); } else if (node instanceof Tree.OptionalType) { Tree.OptionalType ot = (Tree.OptionalType) node; addProposalsForType(ot.getDefiniteType(), proposals); for (String text: proposals) { if (text.startsWith("\\i")) { text = text.substring(2); } proposals.add("maybe" + escaping_.get_().toInitialUppercase(text)); } } else if (node instanceof Tree.SequenceType) { Tree.SequenceType st = (Tree.SequenceType) node; Tree.StaticType et = st.getElementType(); if (et instanceof Tree.SimpleType) { Tree.SimpleType set = (Tree.SimpleType) et; addPluralProposals(proposals, set.getIdentifier(), st.getTypeModel()); } proposals.add("sequence"); } else if (node instanceof Tree.IterableType) { Tree.IterableType it = (Tree.IterableType) node; Tree.Type et = it.getElementType(); if (et instanceof Tree.SequencedType) { Tree.SequencedType st = (Tree.SequencedType) et; et = st.getType(); } if (et instanceof Tree.SimpleType) { Tree.SimpleType set = (Tree.SimpleType) et; addPluralProposals(proposals, set.getIdentifier(), it.getTypeModel()); } proposals.add("stream"); proposals.add("iterable"); } else if (node instanceof Tree.TupleType) { Tree.TupleType tt = (Tree.TupleType) node; List<Tree.Type> ets = tt.getElementTypes(); if (ets.isEmpty()) { proposals.add("none"); proposals.add("empty"); } else if (ets.size()==1) { Tree.Type et = ets.get(0); if (et instanceof Tree.SequencedType) { Tree.SequencedType st = (Tree.SequencedType) et; et = st.getType(); if (et instanceof Tree.SimpleType) { Tree.SimpleType set = (Tree.SimpleType) et; addPluralProposals(proposals, set.getIdentifier(), tt.getTypeModel()); } proposals.add("sequence"); } else { addProposalsForType(et, proposals); proposals.add("singleton"); } } else { addCompoundTypeProposal(ets, proposals, "With"); if (ets.size()==2) { proposals.add("pair"); } else if (ets.size()==3) { proposals.add("triple"); } proposals.add("tuple"); } } else if (node instanceof Tree.FunctionType) { Tree.FunctionType ft = (Tree.FunctionType) node; addProposalsForType(ft.getReturnType(), proposals); proposals.add("callable"); } else if (node instanceof Tree.UnionType) { Tree.UnionType ut = (Tree.UnionType) node; addCompoundTypeProposal(ut.getStaticTypes(), proposals, "Or"); } else if (node instanceof Tree.IntersectionType) { Tree.IntersectionType it = (Tree.IntersectionType) node; addCompoundTypeProposal(it.getStaticTypes(), proposals, "And"); } } public static void addCompoundTypeProposal( List<? extends Tree.Type> ets, Set<String> proposals, String join) { StringBuilder sb = new StringBuilder(); for (Tree.Type t: ets) { Set<String> set = new LinkedHashSet<String>(); addProposalsForType(t, set); String text = set.iterator().next(); if (text!=null) { if (text.startsWith("\\i")) { text = text.substring(2); } if (sb.length()>0) { sb.append(join) .append(escaping_.get_().toInitialUppercase(text)); } else { sb.append(text); } } else { sb = null; break; } } if (sb!=null) { proposals.add(sb.toString()); } } private static Type getLiteralType(Node node, Tree.StaticMemberOrTypeExpression typeExpression) { Unit unit = node.getUnit(); Type pt = typeExpression.getTypeModel(); return unit.isCallableType(pt) ? unit.getCallableReturnType(pt) : pt; } private static void addProposals(Set<String> proposals, Tree.Identifier identifier, Type type) { addNameProposals(proposals, false, identifier.getText()); if (!isTypeUnknown(type)) { if (identifier.getUnit().isIterableType(type)) { addPluralProposals(proposals, identifier, type); } if (type.isString()) { proposals.add("text"); proposals.add("name"); } else if (type.isInteger()) { proposals.add("count"); proposals.add("size"); proposals.add("index"); } } } private static void addPluralProposals(Set<String> proposals, Tree.Identifier identifier, Type type) { if (!isTypeUnknown(type) && !type.isNothing()) { Unit unit = identifier.getUnit(); addNameProposals(proposals, true, unit.getIteratedType(type) .getDeclaration() .getName(unit)); } } }