From 2834ef70d351bdd05289b83232d978dc286acda3 Mon Sep 17 00:00:00 2001
From: Niklas Fors <niklas.fors@cs.lth.se>
Date: Fri, 6 Jul 2018 13:30:54 +0200
Subject: [PATCH] Include supertype when checking for name duplicates

---
 spec/jastadd/Analysis.jrag        | 21 +++++++++++++++------
 tests/errors/Inheritance.expected |  3 +++
 tests/errors/Inheritance.relast   |  6 ++++++
 tests/errors/Makefile             |  9 ++++++++-
 tests/valid/Makefile              |  3 +++
 tests/valid/Test.java             |  2 --
 6 files changed, 35 insertions(+), 9 deletions(-)
 create mode 100644 tests/errors/Inheritance.expected
 create mode 100644 tests/errors/Inheritance.relast

diff --git a/spec/jastadd/Analysis.jrag b/spec/jastadd/Analysis.jrag
index 223a1fb..6ee9e64 100644
--- a/spec/jastadd/Analysis.jrag
+++ b/spec/jastadd/Analysis.jrag
@@ -44,22 +44,31 @@ aspect ComponentAnalysis {
 
 	syn boolean Component.isAlreadyDeclared()
 		= !isTargetOfDirectedRelation()
+			&& toTypeDecl() != null
 			&& lookupComponent(toTypeDecl(), name()) != this;
 	inh Component Component.lookupComponent(TypeDecl td, String name);
-	eq Program.getChild().lookupComponent(TypeDecl td, String name) {
-		if (td != null) {
-			for (Component c: td.getComponents()) {
-				if (c.name().equals(name)) {
-					return c;
-				}
+	eq Program.getChild().lookupComponent(TypeDecl td, String name)
+		= lookupComponentSyn(td, name);
+	syn Component Program.lookupComponentSyn(TypeDecl td, String name) {
+		// Check super type first to find duplicates (shadowing is not allowed)
+		if (td.hasSuper() && td.getSuper().decl() != null) {
+			Component c = lookupComponentSyn(td.getSuper().decl(), name);
+			if (c != null) return c;
+		}
+
+		for (Component c: td.getComponents()) {
+			if (c.name().equals(name)) {
+				return c;
 			}
 		}
+		
 		for (Relation r: getRelations()) {
 			Component c = r.getLeft().lookup(td, name);
 			if (c != null) return c;
 			c = r.getRight().lookup(td, name);
 			if (c != null) return c;
 		}
+
 		return null;
 	}
 
diff --git a/tests/errors/Inheritance.expected b/tests/errors/Inheritance.expected
new file mode 100644
index 0000000..42aab57
--- /dev/null
+++ b/tests/errors/Inheritance.expected
@@ -0,0 +1,3 @@
+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'
diff --git a/tests/errors/Inheritance.relast b/tests/errors/Inheritance.relast
new file mode 100644
index 0000000..9f012a9
--- /dev/null
+++ b/tests/errors/Inheritance.relast
@@ -0,0 +1,6 @@
+A ::= X;
+B1 : A ::= X;
+B2 : A;
+X;
+
+rel B2.X -> X;
diff --git a/tests/errors/Makefile b/tests/errors/Makefile
index 75b5ba0..6d94e59 100644
--- a/tests/errors/Makefile
+++ b/tests/errors/Makefile
@@ -4,4 +4,11 @@ build-jar:
 	(cd ../../ && ant jar)
 test:
 	java -jar ../../relast-compiler.jar Errors.relast 2> Errors.out || true
-	diff Errors.out Errors.expected
\ No newline at end of file
+	diff Errors.out Errors.expected
+
+	java -jar ../../relast-compiler.jar Inheritance.relast 2> Inheritance.out || true
+	diff Inheritance.out Inheritance.expected
+
+	@echo "#"
+	@echo "# ERROR TESTS OK"
+	@echo "#"
\ No newline at end of file
diff --git a/tests/valid/Makefile b/tests/valid/Makefile
index a18b821..786fe1f 100644
--- a/tests/valid/Makefile
+++ b/tests/valid/Makefile
@@ -1,5 +1,8 @@
 all: build-jar test
 test: compile run check-idempotent
+	@echo "#"
+	@echo "# VALID TESTS OK"
+	@echo "#"
 
 build-jar:
 	(cd ../../ && ant jar)
diff --git a/tests/valid/Test.java b/tests/valid/Test.java
index a40c246..c2f0665 100644
--- a/tests/valid/Test.java
+++ b/tests/valid/Test.java
@@ -30,8 +30,6 @@ public class Test {
 		testBi9();
 
 		testImmutableList();
-
-		System.out.println("TESTS OK");
 	}
 
 	/**
-- 
GitLab