net.sourceforge.pmd.lang.modelica.resolver.ModelicaComponentDeclaration Maven / Gradle / Ivy
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.modelica.resolver;
import net.sourceforge.pmd.lang.modelica.ast.ASTComponentClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTComponentDeclaration;
import net.sourceforge.pmd.lang.modelica.ast.ASTConditionAttribute;
import net.sourceforge.pmd.lang.modelica.ast.ASTConstantClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTDeclaration;
import net.sourceforge.pmd.lang.modelica.ast.ASTDiscreteClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTFlowClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTInputClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTName;
import net.sourceforge.pmd.lang.modelica.ast.ASTOutputClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTParameterClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTSimpleName;
import net.sourceforge.pmd.lang.modelica.ast.ASTStreamClause;
import net.sourceforge.pmd.lang.modelica.ast.ASTTypePrefix;
import net.sourceforge.pmd.lang.modelica.ast.ASTTypeSpecifier;
import net.sourceforge.pmd.lang.modelica.resolver.internal.ResolutionContext;
import net.sourceforge.pmd.lang.modelica.resolver.internal.ResolutionState;
import net.sourceforge.pmd.lang.modelica.resolver.internal.Watchdog;
public class ModelicaComponentDeclaration extends AbstractModelicaDeclaration implements ModelicaDeclaration {
public enum ComponentKind {
FLOW("flow"),
STREAM("stream"),
NOTHING_SPECIAL("");
private String name;
ComponentKind(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public enum ComponentVariability {
DISCRETE("discrete"),
PARAMETER("parameter"),
CONSTANT("constant"),
CONTINUOUS("continuous");
private String name;
ComponentVariability(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public enum ComponentCausality {
INPUT("input"),
OUTPUT("output"),
ACAUSAL("acausal");
private String name;
ComponentCausality(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
private ModelicaClassScope containingScope;
private ComponentKind kind;
private ComponentVariability variability;
private ComponentCausality causality;
private final ASTName typeName;
private ResolutionResult typeCandidates;
private final String declarationName;
private final ASTConditionAttribute condition;
public ModelicaComponentDeclaration(ASTComponentDeclaration node) {
declarationName = node.firstChild(ASTDeclaration.class).firstChild(ASTSimpleName.class).getName();
condition = node.firstChild(ASTConditionAttribute.class);
ASTComponentClause declarationRoot = node.ancestors(ASTComponentClause.class).first();
ASTTypePrefix prefixes = declarationRoot.firstChild(ASTTypePrefix.class);
parseTypePrefix(prefixes);
typeName = declarationRoot
.firstChild(ASTTypeSpecifier.class)
.firstChild(ASTName.class);
}
void setContainingScope(ModelicaClassScope scope) {
containingScope = scope;
}
@Override
public ModelicaClassScope getContainingScope() {
return containingScope;
}
private void parseTypePrefix(ASTTypePrefix prefix) {
if (prefix.firstChild(ASTFlowClause.class) != null) {
kind = ComponentKind.FLOW;
} else if (prefix.firstChild(ASTStreamClause.class) != null) {
kind = ComponentKind.STREAM;
} else {
kind = ComponentKind.NOTHING_SPECIAL;
}
if (prefix.firstChild(ASTDiscreteClause.class) != null) {
variability = ComponentVariability.DISCRETE;
} else if (prefix.firstChild(ASTParameterClause.class) != null) {
variability = ComponentVariability.PARAMETER;
} else if (prefix.firstChild(ASTConstantClause.class) != null) {
variability = ComponentVariability.CONSTANT;
} else {
variability = ComponentVariability.CONTINUOUS;
}
if (prefix.firstChild(ASTInputClause.class) != null) {
causality = ComponentCausality.INPUT;
} else if (prefix.firstChild(ASTOutputClause.class) != null) {
causality = ComponentCausality.OUTPUT;
} else {
causality = ComponentCausality.ACAUSAL;
}
}
public ASTConditionAttribute getCondition() {
return condition;
}
/**
* Whether this component is declared as flow
, stream
or nothing special.
*/
public ComponentKind getKind() {
return kind;
}
/**
* Whether this component is a constant, a parameter, a discrete or a continuous variable.
*/
public ComponentVariability getVariability() {
return variability;
}
/**
* Whether this component is input, output or acausal.
*/
public ComponentCausality getCausality() {
return causality;
}
@Override
public String getSimpleDeclarationName() {
return declarationName;
}
@Override
public String getDescriptiveName() {
return declarationName;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (kind != null) {
sb.append(kind.toString());
sb.append(' ');
}
if (variability != null) {
sb.append(variability.toString());
sb.append(' ');
}
if (causality != null) {
sb.append(causality.toString());
sb.append(' ');
}
sb.append(typeName);
sb.append(' ');
sb.append(declarationName);
return sb.toString();
}
public ResolutionResult getTypeCandidates() {
if (typeCandidates == null) {
ResolutionContext ctx = ResolutionState.forComponentReference().createContext();
try {
getContainingScope().resolveLexically(ctx, typeName.getCompositeName());
} catch (Watchdog.CountdownException e) {
ctx.markTtlExceeded();
}
typeCandidates = ctx.getTypes();
}
return typeCandidates;
}
@Override
void resolveFurtherNameComponents(ResolutionContext result, CompositeName name) throws Watchdog.CountdownException {
if (name.isEmpty()) {
result.addCandidate(this);
return;
}
ResolutionResult resolvedType = getTypeCandidates();
for (ModelicaType decl: resolvedType.getBestCandidates()) {
((AbstractModelicaDeclaration) decl).resolveFurtherNameComponents(result, name);
}
result.markHidingPoint();
for (ModelicaType decl: resolvedType.getHiddenCandidates()) {
((AbstractModelicaDeclaration) decl).resolveFurtherNameComponents(result, name);
}
}
}