From aa1b51a34e55be9f514c0c81a7eb002eab3fb5bb Mon Sep 17 00:00:00 2001
From: Xun Yang <x299yang@uwaterloo.ca>
Date: Fri, 6 Mar 2020 22:48:34 -0500
Subject: [PATCH] protected method check

---
 ExprPrimaryNodes.py | 12 ++++++++++--
 NameNode.py         | 34 ++++++++++++++--------------------
 2 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py
index d853c7d..163c0a2 100644
--- a/ExprPrimaryNodes.py
+++ b/ExprPrimaryNodes.py
@@ -2,7 +2,7 @@ from AST import ASTNode, getParseTreeNodes
 from Environment import Env
 from UnitNodes import LiteralNode
 from TheTypeNode import TypeNode, TypeStruct
-from NameNode import NameNode
+from NameNode import NameNode, checkProtected
 
 # file containing smaller (lower level nodes) in the AST
 # nodes in this file:
@@ -388,7 +388,7 @@ class ExprNode(ASTNode):
             self.myType = TypeStruct('java.lang.String', self.env.getNode('java.lang.String', 'type'))
             self.myType.link(self.env)
             return
-        
+
         raise Exception("ERROR: Incompatible types. Left of {} type can't be used with right of {} type on operation {}".format(self.left.myType.name, self.right.myType.name, self.op))
 
 
@@ -425,6 +425,9 @@ class FieldAccessNode(ASTNode):
         self.ID.checkType()
         self.myType = self.ID.myType
 
+        # check protected
+        if "protected" in self.ID.prefixLink.mods:
+            checkProtected(self.ID.prefixLink, self)
 
 
 ###################################################################################
@@ -484,11 +487,16 @@ class MethodInvNode(ASTNode):
         from pprint import pprint
 
         if m:
+            # check static
             if self.ID.shouldBeStatic and (not 'static' in m.mods):
                 raise Exception("ERROR: Static access of non-static method {}.".format(m.name))
             if (not self.ID.shouldBeStatic) and 'static' in m.mods:
                 raise Exception("ERROR: Non-static access of static method {}.".format(m.name))
 
+            # check protected
+            if "protected" in m.mods:
+                checkProtected(m, self)
+
             self.method = m
             self.myType = m.methodType.myType
             return
diff --git a/NameNode.py b/NameNode.py
index 86b3824..2d87cf3 100644
--- a/NameNode.py
+++ b/NameNode.py
@@ -131,16 +131,7 @@ class NameNode(ASTNode):
 
                     # if protected, check if we have access to it
                     if "protected" in typeFieldNode.mods:
-
-                        # get typeFieldNode's class it was declared in
-                        typeFieldNodeClass = typeFieldNode.env.getNode(typeFieldNode.typeName, "type").canonName
-
-                        # get current class we're in
-                        curClass = self.env.getNode(self.typeName, "type")
-
-                        # check to see if typeFieldNode's class is in the current class' super list
-                        if typeFieldNodeClass != curClass.canonName and typeFieldNodeClass not in getSupers(curClass):
-                            raise Exception("ERROR: Class {} is attempting to access a protected field from class {}".format(curClass.canonName, typeFieldNodeClass))
+                        checkProtected(typeFieldNode, self)
 
                     return True
 
@@ -220,16 +211,7 @@ class NameNode(ASTNode):
 
                     # if protected, check if we have access to it
                     if "protected" in curType.mods:
-
-                        # get curType's class it was declared in
-                        typeFieldNodeClass = curType.env.getNode(curType.typeName, "type").canonName
-
-                        # get current class we're in
-                        curClass = self.env.getNode(self.typeName, "type")
-
-                        # check to see if curType's class is in the current class' super list
-                        if typeFieldNodeClass != curClass.canonName and typeFieldNodeClass not in getSupers(curClass):
-                            raise Exception("ERROR: Class {} is attempting to access a protected field from class {}".format(curClass.canonName, typeFieldNodeClass))
+                        checkProtected(curType, self)
 
                 self.prefix = self.prefix + "." + self.IDs[0]
                 self.IDs.pop(0)
@@ -251,3 +233,15 @@ class NameNode(ASTNode):
             # pprint(vars(self.prefixLink))
             # pprint(vars(self))
             raise Exception("ERROR: Cannot check type of name {}".format(self.name))
+
+# helper
+def checkProtected(dcl, usage):
+    # get curType's class it was declared in
+    typeFieldNodeClass = dcl.env.getNode(dcl.typeName, "type")
+
+    # get current class we're in
+    curClass = usage.env.getNode(usage.typeName, "type")
+
+    # check to see if curType's class is in the current class' super list
+    if typeFieldNodeClass.canonName != curClass.canonName and typeFieldNodeClass.canonName not in getSupers(curClass) and typeFieldNodeClass.packageName != curClass.packageName:
+        raise Exception("ERROR: Class {} is attempting to access a protected field from class {}".format(curClass.canonName, typeFieldNodeClass.canonName))
-- 
GitLab