Skip to content
Snippets Groups Projects
Commit fa37120c authored by René Schöne's avatar René Schöne
Browse files

Emit filenames for error messages.

- Extended grammar to let TypeDecl and Relation have filename
- Extended error message to display and order first by filename
- Added testcase with multiple inputs having errors
parent 74ba289c
No related branches found
No related tags found
1 merge request!2Emit filenames for error messages.
Pipeline #4240 passed
......@@ -50,17 +50,33 @@ aspect HelpAttributes {
eq OptionalRelationComponent.multiplicityOpt() = true;
syn boolean RelationComponent.multiplicityMany() = false;
eq ManyRelationComponent.multiplicityMany() = true;
inh ContainedInFile Component.enclosingFileContainer();
eq TypeDecl.getComponent().enclosingFileContainer() = this;
eq Relation.getChild().enclosingFileContainer() = this;
inh ContainedInFile TypeUse.enclosingFileContainer();
eq SimpleTypeComponent.getTypeUse().enclosingFileContainer() = enclosingFileContainer();
eq TokenComponent.getTypeUse().enclosingFileContainer() = enclosingFileContainer();
eq TypeDecl.getSuper().enclosingFileContainer() = this;
syn String ASTNode.containedFile() = "Unknown";
eq Component.containedFile() = enclosingFileContainer() == null ? "Unknown2" : enclosingFileContainer().containedFile();
eq TypeUse.containedFile() = enclosingFileContainer() == null ? "Unknown3" : enclosingFileContainer().containedFile();
eq TypeDecl.containedFile() = getFileName();
eq Relation.containedFile() = getFileName();
}
aspect ErrorMessage {
public class ErrorMessage implements Comparable<ErrorMessage> {
private final ASTNode node;
private final String filename;
private final int line;
private final int col;
private final String message;
public ErrorMessage(ASTNode node, String message) {
this.node = node;
this.filename = node.containedFile();
this.line = node.getStartLine();
this.col = node.getStartColumn();
this.message = message;
......@@ -80,12 +96,17 @@ aspect ErrorMessage {
}
public String toString() {
return "Line " + line + ", column " + col + ": " + message;
return filename + " Line " + line + ", column " + col + ": " + message;
}
@Override
public int compareTo(ErrorMessage err) {
int n = line - err.line;
int n = filename.compareTo(err.filename);
if (n != 0) {
return n;
}
n = line - err.line;
if (n != 0) {
return n;
}
......
Program ::= TypeDecl* Relation*;
TypeDecl ::= <ID> <Abstract:boolean> [Super:TypeUse] Component*;
abstract ContainedInFile ::= <FileName> ;
TypeDecl : ContainedInFile ::= <ID> <Abstract:boolean> [Super:TypeUse] Component*;
abstract Component ::= <ID>;
abstract SimpleTypeComponent : Component ::= TypeUse:SimpleTypeUse;
......@@ -13,7 +14,7 @@ abstract TypeUse ::= <ID>;
SimpleTypeUse : TypeUse;
ParameterizedTypeUse : TypeUse ::= TypeUse*;
Relation ::= Left:RelationComponent Direction Right:RelationComponent;
Relation : ContainedInFile ::= Left:RelationComponent Direction Right:RelationComponent;
abstract RelationComponent : SimpleTypeComponent;
OneRelationComponent : RelationComponent;
OptionalRelationComponent : RelationComponent;
......
......@@ -6,9 +6,23 @@ Program goal =
TypeDecl type_decl =
ID type_decl_super.s components_opt.c SCOL
{: return new TypeDecl(ID, false, s, c); :}
{:
TypeDecl result = new TypeDecl();
result.setID(ID);
result.setAbstract(false);
result.setSuperOpt(s);
result.setComponentList(c);
return result;
:}
| ABSTRACT ID type_decl_super.s components_opt.c SCOL
{: return new TypeDecl(ID, true, s, c); :}
{:
TypeDecl result = new TypeDecl();
result.setID(ID);
result.setAbstract(true);
result.setSuperOpt(s);
result.setComponentList(c);
return result;
:}
;
Opt type_decl_super =
......@@ -38,7 +52,7 @@ List components_opt =
;
List components =
{: return new List(); :}
/* empty */ {: return new List(); :}
| components.l component.c {: return l.add(c); :}
;
......@@ -64,7 +78,13 @@ Component component =
Relation relation =
RELATION relation_comp.l direction relation_comp.r SCOL
{: return new Relation(l, direction, r); :}
{:
Relation result = new Relation();
result.setLeft(l);
result.setDirection(direction);
result.setRight(r);
return result;
:}
;
RelationComponent relation_comp =
......
......@@ -14,7 +14,7 @@ import java.util.List;
public class Compiler {
private static final String VERSION = "0.2.1";
private static final String VERSION = "0.2.2";
private ArrayList<Option<?>> options;
private FlagOption optionWriteToFile;
......@@ -177,9 +177,11 @@ public class Compiler {
try {
Program newProgram = (Program) parser.parse(scanner);
for (TypeDecl typeDecl : newProgram.getTypeDeclList()) {
typeDecl.setFileName(file);
program.addTypeDecl(typeDecl);
}
for (Relation relation : newProgram.getRelationList()) {
relation.setFileName(file);
program.addRelation(relation);
}
} catch (IOException e) {
......
Errors:
Line 5, column 5: Role name missing for type 'A'
Line 6, column 15: Role name missing for type 'B'
Line 7, column 12: The target of a directed relation cannot have a role name
Line 8, column 13: The target of a directed relation may only have multiplicity 1
$FILENAME Line 5, column 5: Role name missing for type 'A'
$FILENAME Line 6, column 15: Role name missing for type 'B'
$FILENAME Line 7, column 12: The target of a directed relation cannot have a role name
$FILENAME Line 8, column 13: The target of a directed relation may only have multiplicity 1
Errors:
Line 2, column 12: Component 'X' is already declared for type 'B1'
Line 6, column 5: Component 'X' is already declared for type 'B2'
$FILENAME Line 2, column 12: Component 'X' is already declared for type 'B1'
$FILENAME Line 6, column 5: Component 'X' is already declared for type 'B2'
Errors:
$FILENAME1 Line 5, column 5: Role name missing for type 'A'
$FILENAME1 Line 6, column 15: Role name missing for type 'B'
$FILENAME2 Line 1, column 12: The target of a directed relation cannot have a role name
$FILENAME2 Line 2, column 13: The target of a directed relation may only have multiplicity 1
Program ::= A* B*;
A;
B;
rel A -> B;
rel A.bs* <-> B*;
rel A.b -> B.b;
rel A.b2 -> B*;
......@@ -9,6 +9,9 @@ import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static org.jastadd.relast.tests.TestHelpers.exec;
import static org.jastadd.relast.tests.TestHelpers.readFile;
......@@ -17,39 +20,33 @@ import static org.jastadd.relast.tests.TestHelpers.readFile;
class Errors {
private static final Logger logger = LogManager.getLogger(Errors.class);
private static final String FILENAME_PATTERN = "$FILENAME";
@Test
void test1() throws IOException {
String inFile = "./src/test/jastadd/errors/Errors.relast";
String outFile = "./src/test/jastadd/errors/Errors.out";
String expectedFile = "./src/test/jastadd/errors/Errors.expected";
try {
System.out.println(System.getProperty("user.dir"));
int returnValue = exec(Compiler.class, new String[]{inFile}, new File(outFile));
Assertions.assertEquals(1, returnValue, "Relast did not return with value 1");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
test("Errors");
}
String out = readFile(outFile, Charset.defaultCharset());
String expected = readFile(expectedFile, Charset.defaultCharset());
Assertions.assertEquals(out, expected);
logger.info("'relast Errors.relast' returned \n{}", out);
@Test
void test2() throws IOException {
test("Inheritance");
}
@Test
void test2() throws IOException {
void test3() throws IOException {
test("Multiple", "Multiple_1", "Multiple_2");
}
String inFile = "./src/test/jastadd/errors/Inheritance.relast";
String outFile = "./src/test/jastadd/errors/Inheritance.out";
String expectedFile = "./src/test/jastadd/errors/Inheritance.expected";
private void test(String name, String... inFilenames) throws IOException {
List<String> inFiles = Arrays.stream(inFilenames.length > 0 ? inFilenames : new String[]{name})
.map(f -> "./src/test/jastadd/errors/" + f + ".relast")
.collect(Collectors.toList());
String outFile = "./src/test/jastadd/errors/" + name + ".out";
String expectedFile = "./src/test/jastadd/errors/" + name + ".expected";
try {
System.out.println(System.getProperty("user.dir"));
int returnValue = exec(Compiler.class, new String[]{inFile}, new File(outFile));
int returnValue = exec(Compiler.class, inFiles.toArray(new String[0]), new File(outFile));
Assertions.assertEquals(1, returnValue, "Relast did not return with value 1");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
......@@ -57,10 +54,16 @@ class Errors {
String out = readFile(outFile, Charset.defaultCharset());
String expected = readFile(expectedFile, Charset.defaultCharset());
if (inFiles.size() == 1) {
expected = expected.replace(FILENAME_PATTERN, inFiles.get(0));
} else {
for (int i = 0; i < inFiles.size(); i++) {
expected = expected.replace(FILENAME_PATTERN + (i + 1), inFiles.get(i));
}
}
Assertions.assertEquals(expected, out);
Assertions.assertEquals(out, expected);
logger.info("'relast Inheritance.relast' returned \n{}", out);
logger.info("relast for " + name + " returned \n{}", out);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment