From d594bacb7d6b5817d3f5b8b2ed73eb807f48c01c Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:21:04 +0200 Subject: [PATCH] Semantic Tests refactored --- src/main/java/semantic/Scope.java | 2 +- src/main/java/semantic/SemanticAnalyzer.java | 2 +- .../AlreadyDeclearedException.java | 2 +- .../AlreadyDefinedException.java | 2 +- .../MultipleReturnTypes.java | 2 +- .../NotDeclearedException.java | 2 +- .../TypeMismatchException.java | 2 +- .../semantic/exceptions/UnknownException.java | 9 + src/test/java/semantic/EndToTAST.java | 282 ------------------ src/test/java/semantic/EndToTypedAstTest.java | 218 ++++++++++++++ src/test/java/semantic/SemanticTest.java | 13 - .../FieldAlreadyDecleared.java | 1 + .../MultipleReturnTypes.java} | 1 + .../NotDecleared.java | 1 + .../ParameterAlreadyDecleared.java | 1 + .../ReturnTypeMismatch.java} | 1 + .../TypeMismatchIntBool.java | 1 + .../TypeMismatchRefType.java | 1 + .../WrongIfClause.java | 1 + .../CorrectReturnType.java} | 0 .../typedAstFeaturesTests}/CorrectTest.java | 0 .../{semantic => trees}/correctRefType.json | 0 .../{semantic => trees}/refTypeMismatch.json | 0 .../resources/{semantic => trees}/test.json | 0 24 files changed, 242 insertions(+), 302 deletions(-) rename src/main/java/semantic/{exeptions => exceptions}/AlreadyDeclearedException.java (84%) rename src/main/java/semantic/{exeptions => exceptions}/AlreadyDefinedException.java (83%) rename src/main/java/semantic/{exeptions => exceptions}/MultipleReturnTypes.java (83%) rename src/main/java/semantic/{exeptions => exceptions}/NotDeclearedException.java (83%) rename src/main/java/semantic/{exeptions => exceptions}/TypeMismatchException.java (83%) create mode 100644 src/main/java/semantic/exceptions/UnknownException.java delete mode 100644 src/test/java/semantic/EndToTAST.java create mode 100644 src/test/java/semantic/EndToTypedAstTest.java rename src/test/resources/{semantic/endToTAST => input/typedAstExceptionsTests}/FieldAlreadyDecleared.java (73%) rename src/test/resources/{semantic/endToTAST/MultipleRetTypes.java => input/typedAstExceptionsTests/MultipleReturnTypes.java} (77%) rename src/test/resources/{semantic/endToTAST => input/typedAstExceptionsTests}/NotDecleared.java (73%) rename src/test/resources/{semantic/endToTAST => input/typedAstExceptionsTests}/ParameterAlreadyDecleared.java (66%) rename src/test/resources/{semantic/endToTAST/retTypeMismatch.java => input/typedAstExceptionsTests/ReturnTypeMismatch.java} (72%) rename src/test/resources/{semantic/endToTAST => input/typedAstExceptionsTests}/TypeMismatchIntBool.java (74%) rename src/test/resources/{semantic/endToTAST => input/typedAstExceptionsTests}/TypeMismatchRefType.java (85%) rename src/test/resources/{semantic/endToTAST => input/typedAstExceptionsTests}/WrongIfClause.java (67%) rename src/test/resources/{semantic/endToTAST/CorrectRetType.java => input/typedAstFeaturesTests/CorrectReturnType.java} (100%) rename src/test/resources/{semantic/endToTAST => input/typedAstFeaturesTests}/CorrectTest.java (100%) rename src/test/resources/{semantic => trees}/correctRefType.json (100%) rename src/test/resources/{semantic => trees}/refTypeMismatch.json (100%) rename src/test/resources/{semantic => trees}/test.json (100%) diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java index 39dd2f8..06647ec 100644 --- a/src/main/java/semantic/Scope.java +++ b/src/main/java/semantic/Scope.java @@ -1,7 +1,7 @@ package semantic; import ast.type.type.*; -import semantic.exeptions.AlreadyDeclearedException; +import semantic.exceptions.AlreadyDeclearedException; import java.util.HashMap; import java.util.Stack; diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index c409c0d..f4461eb 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -25,7 +25,7 @@ import ast.statement.statementexpression.crementExpression.IncrementExpressionNo import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.type.type.*; import semantic.context.Context; -import semantic.exeptions.*; +import semantic.exceptions.*; import typechecker.TypeCheckResult; public class SemanticAnalyzer implements SemanticVisitor { diff --git a/src/main/java/semantic/exeptions/AlreadyDeclearedException.java b/src/main/java/semantic/exceptions/AlreadyDeclearedException.java similarity index 84% rename from src/main/java/semantic/exeptions/AlreadyDeclearedException.java rename to src/main/java/semantic/exceptions/AlreadyDeclearedException.java index d00fd36..d7ffccc 100644 --- a/src/main/java/semantic/exeptions/AlreadyDeclearedException.java +++ b/src/main/java/semantic/exceptions/AlreadyDeclearedException.java @@ -1,4 +1,4 @@ -package semantic.exeptions; +package semantic.exceptions; public class AlreadyDeclearedException extends RuntimeException { diff --git a/src/main/java/semantic/exeptions/AlreadyDefinedException.java b/src/main/java/semantic/exceptions/AlreadyDefinedException.java similarity index 83% rename from src/main/java/semantic/exeptions/AlreadyDefinedException.java rename to src/main/java/semantic/exceptions/AlreadyDefinedException.java index 441a5d9..0128bda 100644 --- a/src/main/java/semantic/exeptions/AlreadyDefinedException.java +++ b/src/main/java/semantic/exceptions/AlreadyDefinedException.java @@ -1,4 +1,4 @@ -package semantic.exeptions; +package semantic.exceptions; public class AlreadyDefinedException extends RuntimeException { diff --git a/src/main/java/semantic/exeptions/MultipleReturnTypes.java b/src/main/java/semantic/exceptions/MultipleReturnTypes.java similarity index 83% rename from src/main/java/semantic/exeptions/MultipleReturnTypes.java rename to src/main/java/semantic/exceptions/MultipleReturnTypes.java index 59f92fa..3f74874 100644 --- a/src/main/java/semantic/exeptions/MultipleReturnTypes.java +++ b/src/main/java/semantic/exceptions/MultipleReturnTypes.java @@ -1,4 +1,4 @@ -package semantic.exeptions; +package semantic.exceptions; public class MultipleReturnTypes extends RuntimeException { diff --git a/src/main/java/semantic/exeptions/NotDeclearedException.java b/src/main/java/semantic/exceptions/NotDeclearedException.java similarity index 83% rename from src/main/java/semantic/exeptions/NotDeclearedException.java rename to src/main/java/semantic/exceptions/NotDeclearedException.java index aa223a0..af1924f 100644 --- a/src/main/java/semantic/exeptions/NotDeclearedException.java +++ b/src/main/java/semantic/exceptions/NotDeclearedException.java @@ -1,4 +1,4 @@ -package semantic.exeptions; +package semantic.exceptions; public class NotDeclearedException extends RuntimeException { diff --git a/src/main/java/semantic/exeptions/TypeMismatchException.java b/src/main/java/semantic/exceptions/TypeMismatchException.java similarity index 83% rename from src/main/java/semantic/exeptions/TypeMismatchException.java rename to src/main/java/semantic/exceptions/TypeMismatchException.java index 93fb62b..2a3fe07 100644 --- a/src/main/java/semantic/exeptions/TypeMismatchException.java +++ b/src/main/java/semantic/exceptions/TypeMismatchException.java @@ -1,4 +1,4 @@ -package semantic.exeptions; +package semantic.exceptions; public class TypeMismatchException extends RuntimeException { diff --git a/src/main/java/semantic/exceptions/UnknownException.java b/src/main/java/semantic/exceptions/UnknownException.java new file mode 100644 index 0000000..8869fdc --- /dev/null +++ b/src/main/java/semantic/exceptions/UnknownException.java @@ -0,0 +1,9 @@ +package semantic.exceptions; + +public class UnknownException extends RuntimeException { + + public UnknownException(String message) { + super(message); + } + +} diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java deleted file mode 100644 index 3189802..0000000 --- a/src/test/java/semantic/EndToTAST.java +++ /dev/null @@ -1,282 +0,0 @@ -package semantic; - -import ast.ASTNode; -import ast.ProgramNode; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.tree.ParseTree; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import parser.astBuilder.ASTBuilder; -import parser.generated.SimpleJavaLexer; -import parser.generated.SimpleJavaParser; -import semantic.exeptions.AlreadyDeclearedException; -import semantic.exeptions.MultipleReturnTypes; -import semantic.exeptions.NotDeclearedException; -import semantic.exeptions.TypeMismatchException; - -import java.io.IOException; -import java.nio.file.Paths; - -import static org.junit.jupiter.api.Assertions.*; - -public class EndToTAST { - - @BeforeEach - public void setup(){ - SemanticAnalyzer.clearAnalyzer(); - } - - @Test - public void CorrectTest(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectTest.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); // parse the input - - /* ------------------------- AST builder -> AST ------------------------- */ - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - - assertEquals(SemanticAnalyzer.errors.size(), 0); - assertNotNull(tast); - - } - - @Test - public void notDecleared() { - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/NotDecleared.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); // parse the input - - /* ------------------------- AST builder -> AST ------------------------- */ - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(NotDeclearedException.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void typeMismatch(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void parameterAlreadyDecleared(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void fieldAlreadyDecleared(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void typeMismatchRefType(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchRefType.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void correctRetType(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectRetType.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertTrue(SemanticAnalyzer.errors.isEmpty()); - - } - - @Test - public void retTypeMismatch(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/retTypeMismatch.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void multipleRetType(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/MultipleRetTypes.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - assertInstanceOf(MultipleReturnTypes.class, SemanticAnalyzer.errors.getFirst()); - - } - - @Test - public void wrongTypeInIfClause(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/WrongIfClause.java")); - } catch (IOException e) { - throw new RuntimeException(e); - } - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); - - ASTBuilder astBuilder = new ASTBuilder(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - assertFalse(SemanticAnalyzer.errors.isEmpty()); - - } - -} diff --git a/src/test/java/semantic/EndToTypedAstTest.java b/src/test/java/semantic/EndToTypedAstTest.java new file mode 100644 index 0000000..9bf5485 --- /dev/null +++ b/src/test/java/semantic/EndToTypedAstTest.java @@ -0,0 +1,218 @@ +package semantic; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; + +import ast.ASTNode; +import ast.ProgramNode; + +import parser.astBuilder.ASTBuilder; +import parser.generated.SimpleJavaLexer; +import parser.generated.SimpleJavaParser; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public class EndToTypedAstTest { + private static final Map> exceptionMap = new HashMap<>(); + + @Test + public void exceptionsTest() { + String directoryPath = "src/test/resources/input/typedAstExceptionsTests"; + File folder = new File(directoryPath); + + try { + loadCustomExceptions(); + System.out.println("Custom exceptions loaded successfully."); + } catch (Exception e) { + throw new RuntimeException("Failed to load custom exceptions", e); + + } + + if (folder.isDirectory()) { + File[] files = folder.listFiles((_, name) -> name.endsWith(".java")); + if (files != null) { + for (File file : files) { + String expectedException = extractExpectedException(file); + + SemanticAnalyzer.clearAnalyzer(); + CharStream codeCharStream; + try { + codeCharStream = CharStreams.fromPath(Paths.get(file.getPath())); + } catch (IOException e) { + throw new RuntimeException(e); + } + + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + if (expectedException != null) { + System.out.println("Testing the file: " + file.getName()); + assertFalse(SemanticAnalyzer.errors.isEmpty(), "Expected an exception, but none was found."); + assertInstanceOf(getExceptionClass(expectedException), SemanticAnalyzer.errors.getFirst()); + } else { + System.out.println("No expected exception specified."); + // If no expected exception is specified, you might want to add a different check + // e.g., assertTrue(SemanticAnalyzer.errors.isEmpty(), "No exceptions expected, but some were found."); + } + } + } else { + System.out.println("No files found in the directory."); + } + } else { + System.out.println("The provided path is not a directory."); + } + } + + @Test + public void featureTest(){ + String directoryPath = "src/test/resources/input/typedAstFeaturesTests"; + File folder = new File(directoryPath); + if (folder.isDirectory()) { + File[] files = folder.listFiles((_, name) -> name.endsWith(".java")); + if (files != null) { + for (File file : files) { + SemanticAnalyzer.clearAnalyzer(); + CharStream codeCharStream; + try { + codeCharStream = CharStreams.fromPath(Paths.get(file.getPath())); + } catch (IOException e) { + throw new RuntimeException(e); + } + + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + System.out.println("Testing the file: " + file.getName()); + assertTrue(SemanticAnalyzer.errors.isEmpty()); + assertNotNull(typedAst); + } + } else { + System.out.println("No files found in the directory."); + } + } else { + System.out.println("The provided path is not a directory."); + } + } + + + + + // ------------------ Helpers ------------------ + /** + * This method is used to extract the expected exception from a given file. + * It reads the file line by line and uses a regular expression to match the expected exception annotation. + * The expected exception annotation should be in the format: "// @expected: ExceptionName". + * If the expected exception annotation is found, it returns the name of the expected exception. + * If the expected exception annotation is not found, it returns null. + * + * @param file The file from which the expected exception is to be extracted. + * @return The name of the expected exception, or null if the expected exception annotation is not found. + */ + private String extractExpectedException(File file) { + String annotationPattern = "//\\s*@expected:\\s*(\\S+)"; + Pattern pattern = Pattern.compile(annotationPattern); + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + return matcher.group(1); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * This method is used to retrieve the Class object associated with a given exception name. + * It first prints the original exception name, then appends the package name to the exception name and prints it. + * It then retrieves the Class object from the exceptionMap using the fully qualified exception name. + * If the Class object is not found in the exceptionMap, it throws a RuntimeException. + * + * @param exceptionName The name of the exception for which the Class object is to be retrieved. + * @return The Class object associated with the given exception name. + * @throws RuntimeException If the Class object for the given exception name is not found in the exceptionMap. + */ +private Class getExceptionClass(String exceptionName) { + System.out.println(exceptionName); + exceptionName = "semantic.exceptions." + exceptionName; + System.out.println(exceptionName); + Class exceptionClass = exceptionMap.get(exceptionName); + if (exceptionClass == null) { + throw new RuntimeException("Exception class not found: " + exceptionName); + } + return exceptionClass; +} + + /** + * This method is used to load custom exceptions from a specified package. + * It first constructs the directory path from the package name and checks if the directory exists. + * If the directory does not exist, it throws an IllegalArgumentException. + * It then creates a URLClassLoader to load the classes from the directory. + * It iterates over all the files in the directory, and for each file, it constructs the class name and loads the class. + * If the loaded class is a subtype of Throwable, it adds the class to the exceptionMap. + * + * @throws Exception If any error occurs during class loading. + */ + private static void loadCustomExceptions() throws Exception { + final String packName = "semantic.exceptions"; + final String dirForMyClasses = "src/main/java/%s".formatted(packName.replace(".", "/")); + File folder = new File(dirForMyClasses); + if (!folder.isDirectory()) { + throw new IllegalArgumentException("The provided path is not a directory."); + } + + URL[] urls = {folder.toURI().toURL()}; + URLClassLoader classLoader; + try { + classLoader = new URLClassLoader(urls); + } catch (Exception e) { + throw new RuntimeException("Failed to create class loader", e); + } + + for (File file : Objects.requireNonNull(folder.listFiles())) { + String className = packName + "." + file.getName().replaceAll("\\.(?:class|java)$", ""); + System.out.printf("Loading custom exception: %s (=> %s)", file.getName(), className); + Class cls = classLoader.loadClass(className); + + if (Throwable.class.isAssignableFrom(cls)) { // Check if the class is a subtype of Throwable + exceptionMap.put(className, cls); + System.out.println("Loaded custom exception: " + className); + } + } + } +} \ No newline at end of file diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index 04fda3d..7680e8a 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -1,18 +1,5 @@ package semantic; -import ast.*; -import ast.member.FieldNode; -import ast.member.MemberNode; -import ast.member.MethodNode; -import ast.parameter.ParameterNode; - -import org.junit.jupiter.api.Test; -import semantic.exeptions.AlreadyDeclearedException; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - public class SemanticTest { diff --git a/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java b/src/test/resources/input/typedAstExceptionsTests/FieldAlreadyDecleared.java similarity index 73% rename from src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java rename to src/test/resources/input/typedAstExceptionsTests/FieldAlreadyDecleared.java index 535a592..3a1ff04 100644 --- a/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java +++ b/src/test/resources/input/typedAstExceptionsTests/FieldAlreadyDecleared.java @@ -1,3 +1,4 @@ +// @expected: AlreadyDeclearedException public class Example { public int a; diff --git a/src/test/resources/semantic/endToTAST/MultipleRetTypes.java b/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java similarity index 77% rename from src/test/resources/semantic/endToTAST/MultipleRetTypes.java rename to src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java index a5680ed..f368e60 100644 --- a/src/test/resources/semantic/endToTAST/MultipleRetTypes.java +++ b/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java @@ -1,3 +1,4 @@ +// @expected: MultipleReturnTypes public class Example { public static int testMethod(int x, char c){ diff --git a/src/test/resources/semantic/endToTAST/NotDecleared.java b/src/test/resources/input/typedAstExceptionsTests/NotDecleared.java similarity index 73% rename from src/test/resources/semantic/endToTAST/NotDecleared.java rename to src/test/resources/input/typedAstExceptionsTests/NotDecleared.java index 4aba5f8..acafa5b 100644 --- a/src/test/resources/semantic/endToTAST/NotDecleared.java +++ b/src/test/resources/input/typedAstExceptionsTests/NotDecleared.java @@ -1,3 +1,4 @@ +// @expected: NotDeclearedException public class Test { public static int testMethod(int x){ int a = b; diff --git a/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java b/src/test/resources/input/typedAstExceptionsTests/ParameterAlreadyDecleared.java similarity index 66% rename from src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java rename to src/test/resources/input/typedAstExceptionsTests/ParameterAlreadyDecleared.java index d2b3425..7de53e0 100644 --- a/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java +++ b/src/test/resources/input/typedAstExceptionsTests/ParameterAlreadyDecleared.java @@ -1,3 +1,4 @@ +// @expected: AlreadyDeclearedException public class Example { public static int testMethod(char a, int a){ diff --git a/src/test/resources/semantic/endToTAST/retTypeMismatch.java b/src/test/resources/input/typedAstExceptionsTests/ReturnTypeMismatch.java similarity index 72% rename from src/test/resources/semantic/endToTAST/retTypeMismatch.java rename to src/test/resources/input/typedAstExceptionsTests/ReturnTypeMismatch.java index d3a2674..6a7f3cc 100644 --- a/src/test/resources/semantic/endToTAST/retTypeMismatch.java +++ b/src/test/resources/input/typedAstExceptionsTests/ReturnTypeMismatch.java @@ -1,3 +1,4 @@ +// @expected: TypeMismatchException public class Example { public static int testMethod(char x){ diff --git a/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchIntBool.java similarity index 74% rename from src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java rename to src/test/resources/input/typedAstExceptionsTests/TypeMismatchIntBool.java index 9b609b6..ec304a2 100644 --- a/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java +++ b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchIntBool.java @@ -1,3 +1,4 @@ +// @expected: TypeMismatchException public class Test { public boolean b; diff --git a/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchRefType.java similarity index 85% rename from src/test/resources/semantic/endToTAST/TypeMismatchRefType.java rename to src/test/resources/input/typedAstExceptionsTests/TypeMismatchRefType.java index a7b8cc9..870b222 100644 --- a/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java +++ b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchRefType.java @@ -1,3 +1,4 @@ +// @expected: TypeMismatchException public class Test { public static int testMethod(ExampleA exampleA, ExampleB exampleB){ diff --git a/src/test/resources/semantic/endToTAST/WrongIfClause.java b/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java similarity index 67% rename from src/test/resources/semantic/endToTAST/WrongIfClause.java rename to src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java index f73f052..e1b7c27 100644 --- a/src/test/resources/semantic/endToTAST/WrongIfClause.java +++ b/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java @@ -1,3 +1,4 @@ +// @expected: TypeMismatchException public class Example { public static void testMethod(int x){ diff --git a/src/test/resources/semantic/endToTAST/CorrectRetType.java b/src/test/resources/input/typedAstFeaturesTests/CorrectReturnType.java similarity index 100% rename from src/test/resources/semantic/endToTAST/CorrectRetType.java rename to src/test/resources/input/typedAstFeaturesTests/CorrectReturnType.java diff --git a/src/test/resources/semantic/endToTAST/CorrectTest.java b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java similarity index 100% rename from src/test/resources/semantic/endToTAST/CorrectTest.java rename to src/test/resources/input/typedAstFeaturesTests/CorrectTest.java diff --git a/src/test/resources/semantic/correctRefType.json b/src/test/resources/trees/correctRefType.json similarity index 100% rename from src/test/resources/semantic/correctRefType.json rename to src/test/resources/trees/correctRefType.json diff --git a/src/test/resources/semantic/refTypeMismatch.json b/src/test/resources/trees/refTypeMismatch.json similarity index 100% rename from src/test/resources/semantic/refTypeMismatch.json rename to src/test/resources/trees/refTypeMismatch.json diff --git a/src/test/resources/semantic/test.json b/src/test/resources/trees/test.json similarity index 100% rename from src/test/resources/semantic/test.json rename to src/test/resources/trees/test.json