/*******************************************************************************
* 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 melnorme.lang.tooling.symbols;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import melnorme.lang.tooling.ast.ILanguageElement;
import melnorme.lang.tooling.ast_actual.ElementDoc;
import melnorme.lang.tooling.engine.ErrorElement.NotAValueErrorElement;
import melnorme.lang.tooling.engine.resolver.ConcreteElementResult;
import melnorme.lang.tooling.engine.resolver.INamedElementSemanticData;
import melnorme.lang.tooling.engine.scoping.CommonScopeLookup;
import melnorme.lang.tooling.engine.scoping.IScopeElement;
import melnorme.lang.tooling.engine.scoping.ScopeTraverser;
import melnorme.utilbox.collections.Collection2;
import melnorme.utilbox.misc.ArrayUtil;
import melnorme.utilbox.misc.IteratorUtil;
import melnorme.utilbox.misc.StringUtil;
import dtool.ast.definitions.EArcheType;
/**
* A package namespace, parented on a given scope, implicitly created from import statements.
*/
public class PackageNamespace extends AbstractResolvedNamedElement implements IScopeElement, IConcreteNamedElement {
public static PackageNamespace createNamespaceElement(String[] packages, INamedElement module) {
String defName = packages[0];
packages = ArrayUtil.copyOfRange(packages, 1, packages.length);
return createNamespaceFragments(defName, packages, module);
}
public static PackageNamespace createNamespaceFragments(String fqName, String[] packages, INamedElement module) {
if(packages.length == 0) {
return new PackageNamespace(fqName, module);
} else {
String childDefName = packages[0];
String childFqName = fqName + "." + childDefName;
packages = ArrayUtil.copyOfRange(packages, 1, packages.length);
PackageNamespace subPackage = createNamespaceFragments(childFqName, packages, module);
return new PackageNamespace(fqName, subPackage);
}
}
/* ----------------- ----------------- */
protected final String fqName;
protected final SymbolTable namedElementsTable;
protected PackageNamespaceSemantics packageNamespaceSemantics;
public PackageNamespace(String fqName, INamedElement firstMember) {
this(fqName, new SymbolTable());
namedElementsTable.addSymbol(assertNotNull(firstMember));
}
protected PackageNamespace(String fqName, SymbolTable namedElementsTable) {
super(StringUtil.substringAfterLastMatch(fqName, "."), null);
this.fqName = fqName;
this.namedElementsTable = assertNotNull(namedElementsTable);
}
public SymbolTable getNamespaceForModification() {
assertTrue(isSemanticReady() == false);
return namedElementsTable;
}
public Collection2<INamedElement> getNamespaceElements() {
return namedElementsTable.getElements();
}
public PackageNamespace doCloneTree() {
SymbolTable newSymbolTable = new SymbolTable();
newSymbolTable.addSymbols(namedElementsTable);
return new PackageNamespace(fqName, newSymbolTable);
}
@Override
protected void doSetElementSemanticReady() {
namedElementsTable.setCompleted();
checkAreSemanticReady(getNamespaceElements(), true);
}
@Override
public EArcheType getArcheType() {
return EArcheType.Package;
}
@Override
public String getFullyQualifiedName() {
return fqName;
}
@Override
public INamedElement getParentNamespace() {
return null;
}
@Override
public INamedElement getContainingModuleNamespace() {
return null;
}
@Override
public boolean isBuiltinElement() {
return false;
}
@Override
public ElementDoc resolveDDoc() {
return null;
}
@Override
public String toString() {
return "PNamespace[" + getFullyQualifiedName() + "]";
}
/* ----------------- ----------------- */
public Iterable<? extends ILanguageElement> getScopeNodeList() {
return IteratorUtil.iterable(getNamespaceElements());
}
@Override
public ScopeTraverser getScopeTraverser() {
return new ScopeTraverser(getScopeNodeList(), true);
}
@Override
public void setElementReady() {
super.setElementReady();
this.packageNamespaceSemantics = new PackageNamespaceSemantics();
}
/* ----------------- ----------------- */
@Override
protected INamedElementSemanticData doGetSemantics() {
return packageNamespaceSemantics;
}
public class PackageNamespaceSemantics implements INamedElementSemanticData {
protected final NotAValueErrorElement notAValueErrorElement = new NotAValueErrorElement(PackageNamespace.this);
protected final ConcreteElementResult concreteResult = new ConcreteElementResult(PackageNamespace.this);
@Override
public INamedElement getTypeForValueContext() {
return notAValueErrorElement;
}
@Override
public void resolveSearchInMembersScope(CommonScopeLookup search) {
search.evaluateScope(PackageNamespace.this);
}
@Override
public ConcreteElementResult resolveConcreteElement() {
return concreteResult;
}
}
}