/******************************************************************************* * Copyright (c) 2010 Bruno Medeiros and other Contributors. * 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.ast.definitions; import static dtool.util.NewUtils.assertCast; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import java.nio.file.Path; import melnorme.lang.tooling.ast.CommonASTNode; import melnorme.lang.tooling.ast.IASTVisitor; import melnorme.lang.tooling.ast.ILanguageElement; import melnorme.lang.tooling.ast.IModuleNode; import melnorme.lang.tooling.ast.SourceRange; import melnorme.lang.tooling.ast.util.ASTCodePrinter; import melnorme.lang.tooling.ast.util.NodeVector; import melnorme.lang.tooling.ast_actual.ASTNode; import melnorme.lang.tooling.ast_actual.ASTNodeTypes; import melnorme.lang.tooling.engine.PickedElement; import melnorme.lang.tooling.engine.resolver.NamedElementSemantics; import melnorme.lang.tooling.engine.resolver.TypeSemantics; import melnorme.lang.tooling.engine.scoping.CommonScopeLookup; import melnorme.lang.tooling.engine.scoping.IScopeElement; import melnorme.lang.tooling.engine.scoping.NamedElementsScope; import melnorme.lang.tooling.engine.scoping.ScopeTraverser; import melnorme.lang.tooling.symbols.IConcreteNamedElement; import melnorme.lang.tooling.symbols.IImportableUnit; import melnorme.lang.tooling.symbols.INamedElement; import melnorme.lang.tooling.symbols.PackageNamespace; import melnorme.utilbox.collections.ArrayView; import dtool.ast.references.RefModule; import dtool.parser.common.BaseLexElement; import dtool.parser.common.IToken; import dtool.parser.common.Token; import dtool.util.NewUtils; /** * D Module. * The top-level AST class, has no parent, is the first and main node of every compilation unit. */ public class Module extends DefUnit implements IModuleNode, IConcreteNamedElement, IScopeElement, IImportableUnit { public static class ModuleDefSymbol extends DefSymbol { protected Module module; public ModuleDefSymbol(String id) { super(id); } @Override protected ASTNode getParent_Concrete() { return assertCast(parent, DeclarationModule.class); } @Override public DefUnit getDefUnit() { return module; } @Override protected CommonASTNode doCloneTree() { return new ModuleDefSymbol(name); } } public static class DeclarationModule extends ASTNode { public final Token[] comments; public final ArrayView<IToken> packageList; public final String[] packages; // Old API public final ModuleDefSymbol moduleName; public DeclarationModule(Token[] comments, ArrayView<IToken> packageList, BaseLexElement moduleDefUnit) { this(comments, packageList, createModuleDefSymbol(moduleDefUnit)); } public DeclarationModule(Token[] comments, ArrayView<IToken> packageList, ModuleDefSymbol moduleDefUnit) { this.comments = comments; this.packageList = assertNotNull(packageList); this.packages = RefModule.tokenArrayToStringArray(packageList); this.moduleName = parentize(moduleDefUnit); } protected static ModuleDefSymbol createModuleDefSymbol(BaseLexElement moduleDefUnit) { ModuleDefSymbol moduleName = new ModuleDefSymbol(moduleDefUnit.getSourceValue()); moduleName.setSourceRange(moduleDefUnit.getSourceRange()); moduleName.setParsedStatus(); return moduleName; } public ModuleDefSymbol getModuleSymbol() { return (ModuleDefSymbol) moduleName; } @Override public ASTNodeTypes getNodeType() { return ASTNodeTypes.DECLARATION_MODULE; } @Override public void visitChildren(IASTVisitor visitor) { acceptVisitor(visitor, moduleName); } @Override protected CommonASTNode doCloneTree() { return new DeclarationModule(comments, packageList, clone(moduleName)); } @Override public void toStringAsCode(ASTCodePrinter cp) { cp.append("module "); cp.appendTokenList(packageList, ".", true); cp.append(moduleName.name); cp.append(";"); } } public static Module createModuleNoModuleDecl(String moduleName, NodeVector<ASTNode> members, Path compilationUnitPath, SourceRange modRange) { ModuleDefSymbol defSymbol = new ModuleDefSymbol(moduleName); defSymbol.setSourceRange(modRange.getStartPos(), 0); return new Module(defSymbol, null, members, compilationUnitPath); } public final DeclarationModule md; public final NodeVector<ASTNode> members; public final Path compilationUnitPath; // can be null. This might be removed in the future. public Module(ModuleDefSymbol defSymbol, DeclarationModule md, NodeVector<ASTNode> members, Path compilationUnitPath) { super(defSymbol, false); defSymbol.module = this; this.md = parentize(md); this.members = parentize(members); assertNotNull(members); this.compilationUnitPath = compilationUnitPath; this.topLevelScope = createTopLevelScope(); } @Override public ASTNodeTypes getNodeType() { return ASTNodeTypes.MODULE; } @Override public void visitChildren(IASTVisitor visitor) { acceptVisitor(visitor, md); acceptVisitor(visitor, members); } @Override protected CommonASTNode doCloneTree() { return new Module((ModuleDefSymbol) clone(defName), clone(md), clone(members), compilationUnitPath); } @Override public void toStringAsCode(ASTCodePrinter cp) { cp.append(md, cp.ST_SEP); cp.appendList(members, cp.ST_SEP); } @Override public EArcheType getArcheType() { return EArcheType.Module; } @Override public INamedElement getContainingModuleNamespace() { return this; } @Override public String getModuleFullName() { return getFullyQualifiedName(); } @Override public String getFullyQualifiedName() { ASTCodePrinter cp = new ASTCodePrinter(); if(md != null) { cp.appendTokenList(md.packageList, ".", true); } cp.append(getName()); return cp.toString(); } public String[] getDeclaredPackages() { if(md != null) { return md.packages; } return NewUtils.EMPTY_STRING_ARRAY; } @Override public Token[] getDocComments() { if(md != null) { return md.comments; } return null; } @Override public Path getCompilationUnitPath() { return compilationUnitPath; } @Override public ILanguageElement getOwnerElement() { return this; } @Override public Path getSemanticContainerKey() { return getCompilationUnitPath(); } /* ----------------- ----------------- */ protected final NamedElementsScope topLevelScope; protected NamedElementsScope createTopLevelScope() { INamedElement topLevelElement = createTopLevelElement(); return new NamedElementsScope(topLevelElement); } protected INamedElement createTopLevelElement() { if(md == null || md.packages.length == 0 || md.packages[0] == "") { return this; } else { String[] packNames = md.packages; return PackageNamespace.createNamespaceElement(packNames, this); } } /* ----------------- ----------------- */ @Override public ScopeTraverser getScopeTraverser() { return new ScopeTraverser(members, true) { @Override public void evaluateSuperScopes(CommonScopeLookup lookup) { lookup.evaluateScope(topLevelScope); lookup.evaluateInMembersScope( CommonScopeLookup.resolveModule(lookup.context, Module.this, "object")); } }; } @Override public IScopeElement getImportableScope() { return importableScope; // Note: we must return same instance of IScopeElement } protected final IScopeElement importableScope = new IScopeElement() { @Override public ScopeTraverser getScopeTraverser() { return new ScopeTraverser(members, true, true); } }; @Override protected NamedElementSemantics doCreateSemantics(PickedElement<?> pickedElement) { return new TypeSemantics(this, pickedElement, new MembersScopeElement(members)); } }