/******************************************************************************* * Copyright (c) 2015, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package dtool.parser.structure; import java.util.EnumSet; import melnorme.lang.tooling.CompletionProposalKind; import melnorme.lang.tooling.EAttributeFlag; import melnorme.lang.tooling.EProtection; import melnorme.lang.tooling.ElementAttributes; import melnorme.lang.tooling.ElementLabelInfo; import melnorme.lang.tooling.structure.StructureElementKind; import melnorme.lang.tooling.symbols.INamedElement; import dtool.ast.declarations.AttribBasic.AttributeKinds; import dtool.ast.definitions.CommonDefinition; import dtool.ast.definitions.DefinitionAlias.DefinitionAliasFragment; import dtool.ast.definitions.DefinitionEnum; import dtool.ast.definitions.DefinitionFunction; import dtool.ast.definitions.EArcheType; import dtool.ast.definitions.EArcheType.ArchetypeCastVisitor; import dtool.ast.definitions.ITemplatableElement; import dtool.ast.references.Reference; import dtool.engine.analysis.IVarDefinitionLike; public class DeeLabelInfoProvider extends ArchetypeCastVisitor { protected StructureElementKind structureKind = null; protected CompletionProposalKind proposalKind = null; protected String type = null; protected ElementAttributes elementAttribs = null; public ElementLabelInfo getLabelInfo(INamedElement element) { visit(element, element.getArcheType()); if(element.isBuiltinElement()) { structureKind = null; proposalKind = CompletionProposalKind.NATIVE; } if(element instanceof IVarDefinitionLike) { IVarDefinitionLike varDef = (IVarDefinitionLike) element; type = getTypeDesc(varDef.getDeclaredType()); } elementAttribs = getAttributes(element); return new ElementLabelInfo(structureKind, proposalKind, type, elementAttribs); } @Override protected void visitModule(INamedElement element) { structureKind = StructureElementKind.MODULEDEC; proposalKind = CompletionProposalKind.MODULEDEC; } @Override protected void visitPackage(INamedElement element) { structureKind = null; // Not a structural element proposalKind = CompletionProposalKind.PACKAGE; } @Override protected void visitVariable(INamedElement element) { structureKind = StructureElementKind.VARIABLE; proposalKind = CompletionProposalKind.VARIABLE; } @Override protected void visitEnumMember(INamedElement element) { structureKind = StructureElementKind.VARIABLE; proposalKind = CompletionProposalKind.VARIABLE; } @Override public void doVisit(DefinitionFunction defFunction) { structureKind = StructureElementKind.FUNCTION; proposalKind = CompletionProposalKind.FUNCTION; type = getTypeDesc(defFunction.retType); } @Override protected void visitConstructor(INamedElement element) { structureKind = StructureElementKind.CONSTRUCTOR; proposalKind = CompletionProposalKind.CONSTRUCTOR; } @Override protected void visitStruct(INamedElement element) { structureKind = StructureElementKind.STRUCT; proposalKind = CompletionProposalKind.STRUCT; } @Override protected void visitUnion(INamedElement element) { structureKind = StructureElementKind.UNION; proposalKind = CompletionProposalKind.UNION; } @Override protected void visitClass(INamedElement element) { structureKind = StructureElementKind.CLASS; proposalKind = CompletionProposalKind.CLASS; } @Override protected void visitInterface(INamedElement element) { structureKind = StructureElementKind.INTERFACE; proposalKind = CompletionProposalKind.INTERFACE; } @Override protected void visitTemplate(INamedElement element) { structureKind = StructureElementKind.TEMPLATE; proposalKind = CompletionProposalKind.TEMPLATE; } @Override public void doVisit(DefinitionEnum defEnum) { structureKind = StructureElementKind.ENUM_TYPE; proposalKind = CompletionProposalKind.ENUM; type = getTypeDesc(defEnum.type); } @Override protected void visitMixin(INamedElement node) { structureKind = StructureElementKind.MIXIN; proposalKind = CompletionProposalKind.MIXIN; } @Override protected void visitAlias(INamedElement node) { structureKind = StructureElementKind.ALIAS; proposalKind = CompletionProposalKind.ALIAS; if(node instanceof DefinitionAliasFragment) { DefinitionAliasFragment aliasFragment = (DefinitionAliasFragment) node; type = getTypeDesc(aliasFragment.target); } else { // TODO: type for other aliases } } @Override protected void visitTuple(INamedElement element) { structureKind = null; // Not a structural element proposalKind = CompletionProposalKind.TUPLE; } @Override protected void visitType(INamedElement element) { structureKind = null; // Not a structural element proposalKind = CompletionProposalKind.TYPE; } @Override protected void visitError(INamedElement element) { structureKind = null; // Not a structural element proposalKind = CompletionProposalKind.ERROR; } /* ----------------- ----------------- */ protected String getTypeDesc(Reference type) { return type == null ? null : type.toStringAsCode(); } public static ElementAttributes getAttributes(INamedElement namedElement) { EnumSet<EAttributeFlag> flagsSet = ElementAttributes.newFlagsSet(); if(namedElement.getArcheType() == EArcheType.Alias) { flagsSet.add(EAttributeFlag.ALIASED); } if(namedElement instanceof CommonDefinition) { CommonDefinition commonDefinition = (CommonDefinition) namedElement; return getDeclarationModifierFlags(commonDefinition, flagsSet); } // TODO: fragment elements return new ElementAttributes(null, flagsSet); } public static ElementAttributes getDeclarationModifierFlags(CommonDefinition elem, EnumSet<EAttributeFlag> flagsSet) { setFlagIfHasAttribute(elem, AttributeKinds.STATIC, flagsSet, EAttributeFlag.STATIC); setFlagIfHasAttribute(elem, AttributeKinds.FINAL, flagsSet, EAttributeFlag.FINAL); // Report these for variable only if(elem.getArcheType() == EArcheType.Variable) { setFlagIfHasAttribute(elem, AttributeKinds.CONST, flagsSet, EAttributeFlag.CONST); setFlagIfHasAttribute(elem, AttributeKinds.IMMUTABLE, flagsSet, EAttributeFlag.IMMUTABLE); } setFlagIfHasAttribute(elem, AttributeKinds.ABSTRACT, flagsSet, EAttributeFlag.ABSTRACT); // set these for Function only if(elem.getArcheType() == EArcheType.Function) { setFlagIfHasAttribute(elem, AttributeKinds.OVERRIDE, flagsSet, EAttributeFlag.OVERRIDE); } if(elem instanceof ITemplatableElement) { ITemplatableElement templatableElement = (ITemplatableElement) elem; if(templatableElement.isTemplated()) { flagsSet.add(EAttributeFlag.TEMPLATED); } } EProtection prot = elem.getEffectiveProtection(); return new ElementAttributes(prot, flagsSet); } public static void setFlagIfHasAttribute(CommonDefinition def, AttributeKinds attrib, EnumSet<EAttributeFlag> flags, EAttributeFlag flag) { if(def.hasAttribute(attrib)) { flags.add(flag); } } }