diff --git a/gradle.properties b/gradle.properties index ddd15d5e..729ff3c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,4 +25,4 @@ assertj_version = 3.21.0 junit_version = 5.8.2 # Version of published artifacts -version = 7.8.79 +version = 7.8.80 diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLExpressionBasisTypeVisitor.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLExpressionBasisTypeVisitor.java new file mode 100644 index 00000000..d862140a --- /dev/null +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLExpressionBasisTypeVisitor.java @@ -0,0 +1,57 @@ +package de.monticore.lang.sysmlv2.types3; + +import de.monticore.expressions.expressionsbasis._ast.ASTNameExpression; +import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisTypeVisitor; +import de.monticore.lang.sysmlv2._symboltable.ISysMLv2Scope; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import de.monticore.types3.util.WithinScopeBasicSymbolsResolver; +import de.se_rwth.commons.logging.Log; + +import java.util.Optional; + +/** + * SysML-spezifische Erweiterung des Typechecks für NameExpressions, einer + * Produktion aus der ExpressionBasis.mc4-Grammatik + */ +public class SysMLExpressionBasisTypeVisitor extends ExpressionBasisTypeVisitor { + + @Override + protected Optional calculateNameExpression(ASTNameExpression expr) { + + if (expr.getEnclosingScope() == null) { + Log.error("0x10AAA internal error: " + + "enclosing scope of expression expected", + expr.get_SourcePositionStart(), + expr.get_SourcePositionEnd() + ); + return Optional.empty(); + } + + final String name = expr.getName(); + IBasicSymbolsScope enclosingScope = getAsBasicSymbolsScope(expr.getEnclosingScope()); + + Optional varResult = + WithinScopeBasicSymbolsResolver.resolveNameAsExpr(enclosingScope, name); + + if (varResult.isPresent()) { + return varResult; + } + + + // Dieser If-Block wurde zum vordefinierten calculateNameExpression hinzugefügt + if (enclosingScope instanceof ISysMLv2Scope) { + Optional typeSymbol = enclosingScope.resolveType(name); + + if (typeSymbol.isPresent()) { + return Optional.of( + SymTypeExpressionFactory.createTypeObject(typeSymbol.get()) + ); + } + } + + return Optional.empty(); + } +} diff --git a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java index 642921ac..6ff5f0a2 100644 --- a/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java +++ b/language/src/main/java/de/monticore/lang/sysmlv2/types3/SysMLTypeCheck3.java @@ -50,7 +50,7 @@ protected static void initTC3Delegate() { Type4Ast type4Ast = new Type4Ast(); // Expressions - var forBasis = new ExpressionBasisTypeVisitor(); + var forBasis = new SysMLExpressionBasisTypeVisitor(); forBasis.setType4Ast(type4Ast); typeTraverser.add4ExpressionsBasis(forBasis); diff --git a/language/src/test/java/cocos/UsingCtrlEnumTypeCheckTest.java b/language/src/test/java/cocos/UsingCtrlEnumTypeCheckTest.java new file mode 100644 index 00000000..8d9c0411 --- /dev/null +++ b/language/src/test/java/cocos/UsingCtrlEnumTypeCheckTest.java @@ -0,0 +1,59 @@ +package cocos; + +import de.monticore.expressions.commonexpressions._ast.ASTFieldAccessExpression; +import de.monticore.expressions.commonexpressions._visitor.CommonExpressionsVisitor2; +import de.monticore.expressions.expressionsbasis._ast.ASTNameExpression; +import de.monticore.lang.sysmlconstraints._ast.ASTConstraintUsage; +import de.monticore.lang.sysmlv2.SysMLv2Mill; +import de.monticore.lang.sysmlv2.SysMLv2Tool; +import de.monticore.lang.sysmlv2._ast.ASTSysMLModel; +import de.monticore.types3.TypeCheck3; +import de.se_rwth.commons.logging.Finding; +import de.se_rwth.commons.logging.Log; +import de.se_rwth.commons.logging.LogStub; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.concurrent.atomic.AtomicReference; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UsingCtrlEnumTypeCheckTest { + + @BeforeEach + public void setup() { + LogStub.init(); + Log.enableFailQuick(false); + Log.clearFindings(); + SysMLv2Mill.reset(); + } + + @Test + public void tryTypeCheckingCtrlEnumName() throws IOException { + SysMLv2Tool tool = new SysMLv2Tool(); + tool.init(); + + var model = "enum def E { enum e; } constraint { E::e }"; + var ast = SysMLv2Mill.parser().parse_String(model).get(); + + tool.createSymbolTable(ast); + tool.completeSymbolTable(ast); + tool.finalizeSymbolTable(ast); + + // extrahiere das "E" aus "enum def ...; constraint { E::e }" im Model + var expr = ((ASTConstraintUsage) ast.getSysMLElement(1)).getExpression(); + var E = ((ASTFieldAccessExpression)expr).getExpression(); + + var type = TypeCheck3.typeOf(E); + + assertThat(type.isObscureType()).isFalse(); + assertThat(type.hasTypeInfo()).isTrue(); + assertThat(type.getTypeInfo().getFullName()).isEqualTo("E"); + + assertThat(Log.getFindings()) + .filteredOn(Finding::isError) + .isEmpty(); + } +}