From ae465edb31cc7b1c76f8d1e0a546b7ea2fee3b7e Mon Sep 17 00:00:00 2001
From: Xun Yang <x299yang@uwaterloo.ca>
Date: Fri, 28 Feb 2020 20:46:48 -0500
Subject: [PATCH] fix import linking stuff

---
 CompNode.py    |  9 +++++++--
 Environment.py | 16 ++++++++++++----
 TypeNodes.py   | 21 ++++++++++++---------
 3 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/CompNode.py b/CompNode.py
index e87e405..819b061 100644
--- a/CompNode.py
+++ b/CompNode.py
@@ -40,14 +40,19 @@ class CompNode(ASTNode):
         return env
 
     def linkType(self):
+        seenImports = set() # check for repeated Imports, which are allowed
+
         for i in self.importNames:
             if ".*" not in i:
                 # add single Type import to self.env under their simple name
                 sImport = self.env.getNode(i, "type")
                 if not sImport:
                     raise Exception("ERROR: Importing non existing type.")
-                self.env.addtoEnv(sImport)
+
+                if i not in seenImports and sImport != self.typeDcl:  # can import self
+                    self.env.addtoEnv(sImport)
+                seenImports.add(i)
             else:
                 # check if on demand import package exists
                 # remove last two char .* to get package name
-                p = self.env.parentEnv.getNodesByPackage(i[:-2])
+                p = self.env.parentEnv.ExistPackage(i[:-2])
diff --git a/Environment.py b/Environment.py
index e8d1ff7..a0ab6fe 100644
--- a/Environment.py
+++ b/Environment.py
@@ -137,10 +137,18 @@ class GlobalEnv(Env):
 
     # method for getting all the nodes under a package (import All)
     # returns a dict of types under that package name
-    def getNodesByPackage(self, pName):
-        if not pName in self.packageMap:
-            raise Exception("ERROR: Can't find definition of package {} in the Environment".format(pName))
-        return self.packageMap.get(pName)
+    def ExistPackage(self, pName):
+        p = pName.split(".")
+        for k in self.packageMap.keys(): #check if package Name is a prefix
+            kk = k.split(".")
+            found = True
+            for i in range(len(p)):
+                if kk[i] != p[i]:
+                    found = False
+                    break
+            if found:
+                return
+        raise Exception("ERROR: Can't find definition of package {} in the Environment".format(pName))
 
 ###################################
 
diff --git a/TypeNodes.py b/TypeNodes.py
index 05bb041..5ed1637 100644
--- a/TypeNodes.py
+++ b/TypeNodes.py
@@ -4,7 +4,7 @@ from Environment import Env
 
 # types: class , interface
 
-class ClassInterNode(ASTNode):    
+class ClassInterNode(ASTNode):
     def checkHierarchy(self):
         # 3. An interface must not be repeated in an implements clause
         if self.superInter:
@@ -13,7 +13,7 @@ class ClassInterNode(ASTNode):
                 if inter.name in unique:
                     raise Exception("ERROR: Class/Interface '{}' implements duplicate interfaces '{}'".format(self.name, inter.name))
                 unique.append(inter.name)
-        
+
         # 7. A class or interface must not declare two methods with the same signature (name and parameter types).
         unique = []
         for method in self.methods:
@@ -21,15 +21,15 @@ class ClassInterNode(ASTNode):
             if key in unique:
                 raise Exception("ERROR: Class/Interface '{}' declares 2 methods with the same signature '{}'".format(self.name, key[0]))
             unique.append(key)
-        
+
         # 6. The hierarchy must be acyclic
         # 9. A class or interface must not contain (declare or inherit) two methods with the same signature but different return types
         # 11. A nonstatic method must not replace a static method
         # 13. A protected method must not replace a public method
-        # 14. A method must not replace a final method
+
         return self.getContains([])
 
-    def getContains(self, hierarchy):        
+    def getContains(self, hierarchy):
         # check if not acyclic
         if self.name in hierarchy:
             raise Exception("ERROR: The hierarchy is not acyclic '{}', saw '{}'".format(hierarchy, self.name))
@@ -37,7 +37,7 @@ class ClassInterNode(ASTNode):
 
         # get contains
         contains = self.methods
-        
+
         for inter in self.superInter:
             superContains = inter.getContains(hierarchy)
             for con in superContains:
@@ -50,11 +50,14 @@ class ClassInterNode(ASTNode):
                         # protected must not replace public
                         if 'protected' in method.mods and 'public' in con.mods:
                             raise Exception("ERROR: Protected method '{}' in class '{}' replaces public method '{}' in class {}".format(method.name, self.name, con.name, inter.name))
+                        # 14. A method must not replace a final method
+                        if 'final' in con.mods:
+                            raise Exception("ERROR: Final method '{}' in class '{}' can't be overrided by method '{}' in class {}".format(method.name, self.name, con.name, inter.name))
                         conOverwritten = True
                         break
                 if not conOverwritten:
                     contains.append(con)
-        
+
         return contains
 
 # class
@@ -150,7 +153,7 @@ class ClassNode(ClassInterNode):
             if key in unique:
                 raise Exception("ERROR: Class '{}' declares 2 constructors with the same parameter types".format(self.name))
             unique.append(key)
-        
+
         # centralized point for overlapping class & interface logic
         contains = super().checkHierarchy()
 
@@ -163,7 +166,7 @@ class ClassNode(ClassInterNode):
     def getContains(self, hierarchy):
         # centralized logic
         contains = super().getContains(hierarchy)
-        
+
         # get contains from extends class
         if self.superClass:
             addToContains = []
-- 
GitLab