aboutsummaryrefslogtreecommitdiff
path: root/ql/ast/checkers
diff options
context:
space:
mode:
Diffstat (limited to 'ql/ast/checkers')
-rw-r--r--ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pycbin0 -> 1953 bytes
-rw-r--r--ql/ast/checkers/__pycache__/question_checker.cpython-35.pycbin0 -> 1658 bytes
-rw-r--r--ql/ast/checkers/__pycache__/reference_checker.cpython-35.pycbin0 -> 2061 bytes
-rw-r--r--ql/ast/checkers/dependency_checker.py44
-rw-r--r--ql/ast/checkers/question_checker.py33
-rw-r--r--ql/ast/checkers/reference_checker.py30
6 files changed, 107 insertions, 0 deletions
diff --git a/ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pyc b/ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pyc
new file mode 100644
index 0000000..5be2eb2
--- /dev/null
+++ b/ql/ast/checkers/__pycache__/dependency_checker.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/checkers/__pycache__/question_checker.cpython-35.pyc b/ql/ast/checkers/__pycache__/question_checker.cpython-35.pyc
new file mode 100644
index 0000000..bb81f4a
--- /dev/null
+++ b/ql/ast/checkers/__pycache__/question_checker.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/checkers/__pycache__/reference_checker.cpython-35.pyc b/ql/ast/checkers/__pycache__/reference_checker.cpython-35.pyc
new file mode 100644
index 0000000..3bdfae5
--- /dev/null
+++ b/ql/ast/checkers/__pycache__/reference_checker.cpython-35.pyc
Binary files differ
diff --git a/ql/ast/checkers/dependency_checker.py b/ql/ast/checkers/dependency_checker.py
new file mode 100644
index 0000000..473ef6b
--- /dev/null
+++ b/ql/ast/checkers/dependency_checker.py
@@ -0,0 +1,44 @@
+class DependencyChecker:
+ def __init__(self, combinations):
+ self.__errors = []
+ self.__check_dependencies(combinations)
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ def __check_dependencies(self, combinations):
+ for (identifier, identifier_children, identifier_metadata) in combinations:
+ children = self.__find_children(identifier, combinations)
+
+ if identifier in children:
+ self.__errors.append('Cyclic dependency detected in question identifiers on line(s) {}'
+ .format(str(self.__find_lines(children, combinations))[1:-1]))
+
+ def __find_children(self, identifier, combinations):
+ reference, reference_children, _ = combinations[0]
+
+ if len(combinations) == 1 and identifier == reference:
+ return reference_children
+ elif len(combinations) == 1:
+ return []
+ elif identifier == reference:
+ all_children = []
+
+ for new_identifier in reference_children:
+ all_children += self.__find_children(new_identifier, combinations[1:])
+
+ return all_children + reference_children
+
+ return self.__find_children(identifier, combinations[1:])
+
+ @staticmethod
+ def __find_lines(children, combinations):
+ lines = []
+
+ for identifier, _, metadata in combinations:
+ for child in children:
+ if identifier == child:
+ lines.append(metadata.line)
+
+ return lines
diff --git a/ql/ast/checkers/question_checker.py b/ql/ast/checkers/question_checker.py
new file mode 100644
index 0000000..5b255d8
--- /dev/null
+++ b/ql/ast/checkers/question_checker.py
@@ -0,0 +1,33 @@
+class QuestionChecker:
+ def __init__(self, questions):
+ self.__errors = []
+ self.__warnings = []
+ self.__check_questions(questions)
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ @property
+ def warnings(self):
+ return self.__warnings
+
+ def __check_questions(self, questions):
+ for question1 in questions:
+ for question2 in questions:
+ if question1 != question2:
+ equal_labels = question1['label'] == question2['label']
+ equal_identifiers = question1['identifier'] == question2['identifier']
+ different_types = question1['answer_type'] != question2['answer_type']
+
+ if all([equal_labels, equal_identifiers, different_types]):
+ self.__errors.append('Duplicate questions with different types found on lines {} and {}'
+ .format(question1['metadata'].line, question2['metadata'].line))
+
+ if equal_identifiers:
+ self.__errors.append('Duplicate question identifiers found on lines {} and {}'
+ .format(question1['metadata'].line, question2['metadata'].line))
+
+ if equal_labels:
+ self.__warnings.append('Duplicate question labels found on lines {} and {}'
+ .format(question1['metadata'].line, question2['metadata'].line))
diff --git a/ql/ast/checkers/reference_checker.py b/ql/ast/checkers/reference_checker.py
new file mode 100644
index 0000000..71407c3
--- /dev/null
+++ b/ql/ast/checkers/reference_checker.py
@@ -0,0 +1,30 @@
+class ReferenceChecker:
+ def __init__(self, table):
+ self.__errors = []
+ self.__check_references(table, [], [])
+
+ @property
+ def errors(self):
+ return self.__errors
+
+ def __check_references(self, table, known_types, unknown_types):
+ (local_known_types, local_unknown_types) = self.__split_known_unknown_types(table)
+ known_types += local_known_types
+ unknown_types += local_unknown_types
+
+ self.__identifier_seen(known_types, unknown_types)
+
+ if table['children']:
+ for child_scope in table['children']:
+ self.__check_references(child_scope, known_types, unknown_types)
+
+ @staticmethod
+ def __split_known_unknown_types(table):
+ known_types = [row['name'] for row in table['content'] if row['type']]
+ unknown_types = [(row['name'], row['line']) for row in table['content'] if not (row['type'])]
+ return known_types, unknown_types
+
+ def __identifier_seen(self, known_types, unknown_types):
+ for (identifier, line) in unknown_types:
+ if not (identifier in known_types):
+ self.__errors.append('Identifier \"{}\" at line {} is unknown'.format(identifier, line))