E2E Running
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

Other tests and make refactored
This commit is contained in:
Lucas 2024-07-04 14:35:02 +02:00
parent 2934872457
commit f7a4e65093
6 changed files with 2233 additions and 206 deletions

18
pom.xml
View File

@ -35,6 +35,12 @@
<version>5.11.0-M2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
@ -56,18 +62,6 @@
<version>3.26.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>

77
readme.md Normal file
View File

@ -0,0 +1,77 @@
# "Nicht Haskel 2.0" Java Compiler
Realisation of a subset of the Java Standard Compiler in the course Compiler Construction of the 4th semester Computer Science at the Duale Hochschule Suttgart (Horb).
This project aims to provide a simplified version of the Java compiler, focusing on key language features and demonstrating the principles of compiler construction.
## Realised Java syntax
- **Data types**: `int`, `boolean`, `char`
- **Access modifier**: `public`, `protected`, `private`
- **Operators**: `=` `+` `-` `*` `%` `/` `>` `<` `>=` `<=` `==` `!=` `!` `&&` `||` `++` `--`
- **Keywords**: `class`, `this`, `while`, `do`, `if`, `else`, `for`, `return`, `new`, `switch`, `case`, `break`, `default`, `:`
- **Statements**:
- `if` ... `if else` ... `else`;
- `while` ... ;
- `do` ... `while`;
- `for`;
- `switch` ... `case` ... ;
- **Comments**:
- Single line: `// comment`
- Multi-line: `/* comment */`
- **Further functions**:
- All methods are overloadable
- High maintainability and expandability through implementation of the visitor pattern
- Logging Input and Outputs
- Error Handling in the Semantic Check
## Project Structure
```plain
src/
└── main/
├── java/
│ ├── ast/ -> Defining the structure of the AST
│ ├── bytecode/ -> Generate Java bytecode
│ ├── main/ -> Running the compiler
│ ├── parser/
│ │ ├── astBuilder/ -> Builder creating the AST
│ │ ├── generated/ -> Antlr generated grammar
│ │ └── grammar/ -> Antlr grammar
│ ├── semantic/ -> Running the semantic check
│ └── visitor/ -> Visitor interface
└── resources/
test/
└── java/
│ ├── main/
│ ├── parser/ -> Performs tests on the parser
│ └── semantic/
└── resources/ -> Ressources for running the Tests
├──input
│ ├── combinedFeatureTests
│ ├── endabgabeTests
│ ├── failureTests
│ ├── singleFeatureSemanticTests
│ ├── singleFeatureTests
│ ├── typedAstExceptionsTests
│ └── typedAstFeatureTests
└──output
├── javac
└── raupenpiler
```
## Class-Diagramm AST
![AST Diagramm](ast.png)
## Used Tools
- [Maven 4.0](https://maven.apache.org/index.html)
- Used for automating the build process and managing dependencies.
- [ANTLR4 v.13.1](https://www.antlr.org/)
- Used to parse the input Java code into the Abstract Syntax Tree.
## How to run the compiler
## Download
```bash

View File

@ -29,11 +29,13 @@ test-raupenpiler:
clean:
# clean output folders
# clean main output folders
rm -f ../main/resources/output/*.class
rm -f ../main/resources/output/*.jar
# clean resources output folders
rm -f ./resources/output/javac/*.class
rm -f ./resources/output/raupenpiler/*.class
rm -f ./resources/output/raupenpiler/*.jar
# clean logs
rm -f ../main/resources/logs/*.log
# clean test/java/main folders from .class files for End-to-End tests

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
package main;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import javax.tools.JavaCompiler;
@ -51,6 +52,133 @@ public class InputFilesTest {
}
}
@Test
public void areCombinedFeatureTestsValid() throws IOException {
// Get the system Java compiler
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
// Assert that the compiler is available
assertNotNull(javac, "Java Compiler is not available");
File combinedFeatureTests = new File("src/test/resources/input/combinedFeatureTests");
List<File> files = getJavaFilesFromDirectory(combinedFeatureTests);
if (!files.isEmpty()) {
for (File file : files) {
// Try to compile the file and get the result
int result = javac.run(null, null, null, file.getPath());
// Assert that the compilation succeeded (i.e., the result is zero)
assertEquals(0, result, "Expected compilation success for " + file.getName());
}
} else {
System.out.println("No files found in the directories.");
}
}
@Test
@Disabled
public void areEndabgabeTestsActuallyValid() throws IOException {
// Get the system Java compiler
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
// Assert that the compiler is available
assertNotNull(javac, "Java Compiler is not available");
File endabgabeTests = new File("src/test/resources/input/endabgabeTests");
List<File> files = getJavaFilesFromDirectory(endabgabeTests);
if (!files.isEmpty()) {
for (File file : files) {
// Try to compile the file and get the result
int result = javac.run(null, null, null, file.getPath());
// Assert that the compilation succeeded (i.e., the result is zero)
assertEquals(0, result, "Expected compilation success for " + file.getName());
}
} else {
System.out.println("No files found in the directories.");
}
}
@Test
@Disabled
public void areSingleFeatureSemanticTestsActuallyValid() throws IOException {
// Get the system Java compiler
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
// Assert that the compiler is available
assertNotNull(javac, "Java Compiler is not available");
File singleFeatureSemanticTests = new File("src/test/resources/input/singleFeatureSemanticTests");
List<File> files = getJavaFilesFromDirectory(singleFeatureSemanticTests);
if (!files.isEmpty()) {
for (File file : files) {
// Try to compile the file and get the result
int result = javac.run(null, null, null, file.getPath());
// Assert that the compilation succeeded (i.e., the result is zero)
assertEquals(0, result, "Expected compilation success for " + file.getName());
}
} else {
System.out.println("No files found in the directories.");
}
}
@Test
public void areSingleFeatureTestsActuallyValid() throws IOException {
// Get the system Java compiler
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
// Assert that the compiler is available
assertNotNull(javac, "Java Compiler is not available");
File singleFeatureTests = new File("src/test/resources/input/singleFeatureTests");
List<File> files = getJavaFilesFromDirectory(singleFeatureTests);
if (!files.isEmpty()) {
for (File file : files) {
// Try to compile the file and get the result
int result = javac.run(null, null, null, file.getPath());
// Assert that the compilation succeeded (i.e., the result is zero)
assertEquals(0, result, "Expected compilation success for " + file.getName());
}
} else {
System.out.println("No files found in the directories.");
}
}
@Test
@Disabled
public void areTypedAstFeatureTestsActuallyValid() throws IOException {
// Get the system Java compiler
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
// Assert that the compiler is available
assertNotNull(javac, "Java Compiler is not available");
File typedAstFeatureTests = new File("src/test/resources/input/typedAstFeatureTests");
List<File> files = getJavaFilesFromDirectory(typedAstFeatureTests);
if (!files.isEmpty()) {
for (File file : files) {
// Try to compile the file and get the result
int result = javac.run(null, null, null, file.getPath());
// Assert that the compilation succeeded (i.e., the result is zero)
assertEquals(0, result, "Expected compilation success for " + file.getName());
}
} else {
System.out.println("No files found in the directories.");
}
}
/**
* This test method checks if invalid Java files fail to compile as expected.

View File

@ -1,145 +0,0 @@
package main;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import org.antlr.v4.runtime.CharStream;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ReflectionsTest {
@Test
public void testSimpleJavaLexerClass() throws ClassNotFoundException, NoSuchMethodException {
Class<?> clazz = Class.forName("parser.generated.SimpleJavaLexer");
// Class Name
assertEquals("parser.generated.SimpleJavaLexer", clazz.getName());
// Constructors
Constructor<?>[] actualConstructors = clazz.getDeclaredConstructors();
assertTrue(actualConstructors.length > 0, "No constructors found");
Constructor<?> expectedConstructor = clazz.getConstructor(CharStream.class);
boolean constructorFound = false;
for (Constructor<?> constructor : actualConstructors) {
if (constructor.equals(expectedConstructor)) {
constructorFound = true;
break;
}
}
assertTrue(constructorFound, "Expected constructor not found in actual constructors");
// Methods
Method[] actualMethodNames = clazz.getDeclaredMethods();
assertTrue(actualMethodNames.length > 0);
Arrays.stream(actualMethodNames).forEach(method -> System.out.println("Method: " + method.getName()));
List<String> expectedMethodNames = Arrays.asList(
"getTokenNames",
"getVocabulary",
"getGrammarFileName",
"getRuleNames",
"getSerializedATN",
"getChannelNames",
"getModeNames",
"getATN",
"makeRuleNames",
"makeLiteralNames",
"makeSymbolicNames"
);
for (Method method : actualMethodNames) {
assertTrue(expectedMethodNames.contains(method.getName()));
}
for (String expectedMethodName : expectedMethodNames) {
boolean methodFound = false;
for (Method method : actualMethodNames) {
if (method.getName().equals(expectedMethodName)) {
methodFound = true;
break;
}
}
assertTrue(methodFound, "Expected method " + expectedMethodName + " not found in actual methods");
}
// Fields
Field[] actualFieldNames = clazz.getDeclaredFields();
assertTrue(actualFieldNames.length > 0);
Arrays.stream(actualFieldNames).forEach(field -> System.out.println("Field: " + field.getName()));
List<String> expectedFieldNames = Arrays.asList(
"_decisionToDFA",
"_sharedContextCache",
"channelNames",
"modeNames",
"ruleNames",
"_LITERAL_NAMES",
"_SYMBOLIC_NAMES",
"VOCABULARY",
"tokenNames",
"_serializedATN",
"_ATN"
);
for (Field field : actualFieldNames) {
assertTrue(expectedFieldNames.contains(field.getName()));
}
}
@Test
public void testSimpleJavaParserClass() throws ClassNotFoundException {
Class<?> clazz = Class.forName("parser.generated.SimpleJavaParser");
// Class Name
assertEquals("parser.generated.SimpleJavaParser", clazz.getName());
// Constructors
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
assertTrue(constructors.length > 0);
// Methods
Method[] methods = clazz.getDeclaredMethods();
assertTrue(methods.length > 0);
Arrays.stream(methods).forEach(method -> System.out.println("Method: " + method.getName()));
// Fields
Field[] fields = clazz.getDeclaredFields();
assertTrue(fields.length > 0);
Arrays.stream(fields).forEach(field -> System.out.println("Field: " + field.getName()));
}
@Test
public void testASTBuilderClass() throws ClassNotFoundException {
Class<?> clazz = Class.forName("parser.astBuilder.ASTBuilder");
// Class Name
assertEquals("parser.astBuilder.ASTBuilder", clazz.getName());
// Constructors
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
assertTrue(constructors.length > 0);
// Methods
Method[] methods = clazz.getDeclaredMethods();
assertTrue(methods.length > 0);
Arrays.stream(methods).forEach(method -> System.out.println("Method: " + method.getName()));
// Fields
Field[] fields = clazz.getDeclaredFields();
assertTrue(fields.length > 0);
Arrays.stream(fields).forEach(field -> System.out.println("Field: " + field.getName()));
}
// Similarly, you can add tests for SemanticAnalyzer and ByteCodeGenerator
}