/******************************************************************************* * 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.ast.definitions; import static melnorme.utilbox.misc.IteratorUtil.nonNullIterable; import melnorme.lang.tooling.ast.CommonASTNode; import melnorme.lang.tooling.ast.IASTVisitor; import melnorme.lang.tooling.ast.ILanguageElement; import melnorme.lang.tooling.ast.util.ASTCodePrinter; import melnorme.lang.tooling.ast.util.NodeVector; import melnorme.lang.tooling.context.ISemanticContext; import melnorme.lang.tooling.engine.PickedElement; import melnorme.lang.tooling.engine.scoping.CommonScopeLookup; import melnorme.lang.tooling.engine.scoping.ScopeTraverser; import melnorme.lang.tooling.symbols.INamedElement; import melnorme.utilbox.core.CoreUtil; import dtool.ast.expressions.Expression; import dtool.ast.references.Reference; import dtool.engine.analysis.DeeLanguageIntrinsics; import dtool.parser.common.Token; /** * A definition of a class aggregate. */ public abstract class DefinitionClass_Common extends DefinitionAggregate { public final NodeVector<Reference> baseClasses; public final boolean baseClassesAfterConstraint; public DefinitionClass_Common(Token[] comments, DefSymbol defId, NodeVector<ITemplateParameter> tplParams, Expression tplConstraint, NodeVector<Reference> baseClasses, boolean baseClassesAfterConstraint, IAggregateBody aggrBody) { super(comments, defId, tplParams, tplConstraint, aggrBody); this.baseClasses = parentize(baseClasses); this.baseClassesAfterConstraint = baseClassesAfterConstraint; } @Override public final void visitChildren(IASTVisitor visitor) { acceptNodeChildren(visitor); } @Override protected CommonASTNode doCloneTree() { return new DefinitionClass(comments, clone(defName), clone(tplParams), clone(tplConstraint), clone(baseClasses), baseClassesAfterConstraint, clone(aggrBody)); } public void classLikeToStringAsCode(ASTCodePrinter cp, String keyword) { cp.append(keyword); cp.append(defName, " "); cp.appendList("(", tplParams, ",", ") "); if(baseClassesAfterConstraint) DefinitionTemplate.tplConstraintToStringAsCode(cp, tplConstraint); cp.appendList(": ", baseClasses, ",", " "); if(!baseClassesAfterConstraint) DefinitionTemplate.tplConstraintToStringAsCode(cp, tplConstraint); cp.append(aggrBody, "\n"); } @Override protected void acceptNodeChildren(IASTVisitor visitor) { acceptVisitor(visitor, defName); acceptVisitor(visitor, tplParams); if(baseClassesAfterConstraint) acceptVisitor(visitor, tplConstraint); acceptVisitor(visitor, baseClasses); if(!baseClassesAfterConstraint) acceptVisitor(visitor, tplConstraint); acceptVisitor(visitor, aggrBody); } /* ----------------- ----------------- */ @Override public ScopeTraverser getScopeTraverser() { return new ScopeTraverser(tplParams, false) { @Override public void evaluateSuperScopes(CommonScopeLookup lookup) { getSemantics(lookup.context).getMembersScope().resolveLookupInSuperScopes(lookup); } }; } /* ----------------- ----------------- */ @Override public final ClassSemantics getSemantics(ISemanticContext parentContext) { return (ClassSemantics) super.getSemantics(parentContext); } @Override protected ClassSemantics doCreateSemantics(PickedElement<?> pickedElement) { return new ClassSemantics(this, pickedElement); } public class ClassSemantics extends AggregateSemantics { public ClassSemantics(DefinitionClass_Common classElement, PickedElement<?> pickedElement) { super(classElement, pickedElement, new DefClassMembersScope(getAggregateMembers()), DeeLanguageIntrinsics.D2_063_intrinsics.createObjectPropertiesScope(classElement)); } @Override public DefClassMembersScope getMembersScope() { return (DefClassMembersScope) super.getMembersScope(); } public INamedElement resolveSuperClass(ISemanticContext mr) { for (Reference baseClassRef : nonNullIterable(baseClasses)) { INamedElement baseClass = baseClassRef.resolveTargetElement(mr); if(baseClass.getArcheType() == EArcheType.Interface) { continue; } if(baseClass.getArcheType() == EArcheType.Class) { return baseClass; } } // TODO test implicit object reference return DeeLanguageIntrinsics.OBJECT_CLASS_REF.getSemantics(mr).resolveTargetElement().result; } } public class DefClassMembersScope extends MembersScopeElement { public DefClassMembersScope(Iterable<? extends ILanguageElement> membersIterable) { super(membersIterable); } @Override public void resolveLookupInSuperScopes(CommonScopeLookup search) { ISemanticContext context = search.context; for(Reference baseclass : CoreUtil.nullToEmpty(baseClasses)) { INamedElement baseClassElem = baseclass.resolveTargetElement(context); if(baseClassElem == null) continue; if(baseClassElem instanceof DefinitionClass_Common) { DefinitionClass_Common baseClassDef = (DefinitionClass_Common) baseClassElem; search.evaluateScope(baseClassDef.getSemantics(context).getMembersScope()); } } } } }