/******************************************************************************* * Copyright (c) 2011 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.engine.analysis; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import melnorme.lang.tooling.ast.INamedElementNode; import melnorme.lang.tooling.ast_actual.ElementDoc; import melnorme.lang.tooling.context.ISemanticContext; import melnorme.lang.tooling.engine.ErrorElement; import melnorme.lang.tooling.engine.PickedElement; import melnorme.lang.tooling.engine.resolver.AliasSemantics; import melnorme.lang.tooling.engine.resolver.NamedElementSemantics; import melnorme.lang.tooling.engine.scoping.CommonScopeLookup; import melnorme.lang.tooling.symbols.AbstractNamedElement; import melnorme.lang.tooling.symbols.IConcreteNamedElement; import melnorme.lang.tooling.symbols.INamedElement; import melnorme.utilbox.misc.StringUtil; import dtool.ast.definitions.EArcheType; import dtool.ast.references.RefModule; /** * This class is an alias to an actual module element. * Used for performance reasons, to be able to use the proxy in some situations (Content Assist for example) * without forcing the referred module to be parsed. */ public class ModuleProxy extends AbstractNamedElement { protected final RefModule refModule; // non-child protected final ISemanticContext context; protected final String fullModuleName; public ModuleProxy(String fullModuleName, ISemanticContext moduleResolver, RefModule owner) { this(fullModuleName, moduleResolver, false, owner); } public ModuleProxy(String fullModuleName, ISemanticContext moduleResolver, boolean useFullName, RefModule refModule) { super(getEffectiveModuleName(fullModuleName, useFullName), null, refModule); this.refModule = assertNotNull(refModule); assertTrue(getName().trim().isEmpty() == false); this.fullModuleName = fullModuleName; this.context = moduleResolver; setElementReady(); } protected static String getEffectiveModuleName(String fullModuleName, boolean usefullName) { return usefullName ? fullModuleName : StringUtil.substringAfterLastMatch(fullModuleName, "."); } @Override protected void doSetElementSemanticReady() { assertTrue(refModule.isSemanticReady()); } @Override public String toString() { return "module["+getModuleFullName()+"]"; } @Override public EArcheType getArcheType() { return EArcheType.Module; } @Override public INamedElement getContainingModuleNamespace() { return this; } @Override public String getModuleFullName() { return fullModuleName; } @Override public String getFullyQualifiedName() { return fullModuleName; } @Override public INamedElement getParentNamespace() { return null; } @Override public INamedElementNode resolveUnderlyingNode() { INamedElement module = resolveConcreteElement(); if(module instanceof INamedElementNode) { return (INamedElementNode) module; } return null; } @Override public ElementDoc resolveDDoc() { IConcreteNamedElement resolvedModule = resolveConcreteElement(); if(resolvedModule != null) { return resolvedModule.resolveDDoc(); } return null; } public IConcreteNamedElement resolveConcreteElement() { return resolveConcreteElement(context); } /* ----------------- ----------------- */ @Override public ISemanticContext getElementSemanticContext(ISemanticContext parentContext) { return context; } @Override protected final NamedElementSemantics doCreateSemantics(PickedElement<?> pickedElement) { return new AliasSemantics(this, pickedElement) { { assertTrue(context == ModuleProxy.this.context); } @Override protected IConcreteNamedElement resolveAliasTarget_nonNull() { IConcreteNamedElement result = CommonScopeLookup.resolveModule(context, ModuleProxy.this, getModuleFullName()); if(result == null) { return new ErrorElement.NotFoundErrorElement(refModule); } return result; } }; } }