[Tools] Add Code Checker (#472)
authorJay Cho <chojoong@gmail.com>
Tue, 18 Sep 2018 05:19:38 +0000 (14:19 +0900)
committerWonYoung Choi <wy80.choi@samsung.com>
Tue, 18 Sep 2018 05:19:38 +0000 (14:19 +0900)
* Add Code Checker

* Add existing comment check

* Move code checker files to scripts folder

tools/scripts/CodeChecker/BuildLog.py [new file with mode: 0644]
tools/scripts/CodeChecker/PRManager.py [new file with mode: 0644]
tools/scripts/CodeChecker/main.py [new file with mode: 0644]

diff --git a/tools/scripts/CodeChecker/BuildLog.py b/tools/scripts/CodeChecker/BuildLog.py
new file mode 100644 (file)
index 0000000..4896b2c
--- /dev/null
@@ -0,0 +1,31 @@
+class BuildLog:
+    FILE = 0
+    LINE_NUMBER = 1
+    WARNING_CODE = 2
+    MESSAGE = 3
+
+    def __init__(self, filePath):
+        self._file = open(filePath, 'r')
+        self._parseLog()
+
+    def _parseLog(self):
+        self._lines = self._file.readlines()
+        self._lines[:] = [line for line in self._lines if ": warning" in line]
+        self.warnings = [[0 for i in range(4)] for y in range(len(self._lines))]
+
+        for index, line in enumerate(self._lines):
+            self._lines[index] = line.split(":")
+            self._lines[index][0] = self._lines[index][0][:-1].split("(")
+
+            self.warnings[index][self.FILE] = self._lines[index][0][0]
+            self.warnings[index][self.LINE_NUMBER] = int(self._lines[index][0][1].split(",")[0])
+            self.warnings[index][self.WARNING_CODE] = self._lines[index][1]
+            self.warnings[index][self.MESSAGE] = self._lines[index][2].split("[/")[0]
+
+    def __del__(self):
+        self._file.close()
+
+if __name__ == "__main__":
+    logPath = "../../build.log"
+    logs = BuildLog(logPath)
+    print(logs.warnings)
diff --git a/tools/scripts/CodeChecker/PRManager.py b/tools/scripts/CodeChecker/PRManager.py
new file mode 100644 (file)
index 0000000..3b4abdd
--- /dev/null
@@ -0,0 +1,62 @@
+import os
+from github import Github
+
+gitHubRepo = "Samsung/TizenFX"
+token = os.environ['TizenAPI-Bot-Token']
+
+class PRManager:
+    def __init__(self, prNumber):
+        self._gh = Github(token)
+        self.pr = self._gh.get_repo(gitHubRepo).get_pull(prNumber)
+
+        self.latestCommit = self.pr.get_commits().reversed[0]
+        self.changedFiles = self.pr.get_files()
+
+        self.lineNumberToPositionMap = {}
+        self.fileDiffHunkPairs = {}
+
+        for file in self.changedFiles:
+            _patchLines = file.patch.split("\n")
+            self._CreatePositionMap(file, _patchLines)
+            _patchLines[:] = [line for line in _patchLines if "@@" in line]
+            _diffLines = []
+            for hunkline in _patchLines:
+                hunkline = hunkline[2:]
+                startingLine = hunkline[hunkline.find("+")+1:hunkline.find("@@")]
+                startingLine = startingLine.strip()
+                startingLine = startingLine.split(",")
+                _diffLines.insert(0, map(int, startingLine))
+            _diffLines.reverse()
+            self.fileDiffHunkPairs[file] = _diffLines
+
+    def _CreatePositionMap(self, file, patchLines):
+        self.lineNumberToPositionMap[file] = {}
+        for position, line in enumerate(patchLines):
+            if line[0] == "@":
+                line = line[line.find("+")+1:]
+                lineNumber = int(line[:line.find(",")])
+                continue
+            elif line[0] == "-":
+                continue
+            self.lineNumberToPositionMap[file][lineNumber] = position
+            lineNumber += 1
+
+    def _CheckComment(self, file, position, body):
+        _comments = self.pr.get_comments();
+        for comment in _comments:
+            if (comment.path == file and comment.position == position and comment.body == body):
+                # Comment already exists
+                return False
+        return True
+
+    def CreateReviewComment(self, file, lineNumber, body):
+        _position = self.lineNumberToPositionMap[file][lineNumber]
+        if self._CheckComment(file.filename, _position, body):
+            self.pr.create_review_comment(body, self.latestCommit, file.filename, _position)
+
+if __name__ == "__main__":
+    pr = 9
+    gh = PRManager(pr)
+    for file in gh.changedFiles:
+        print("Chaged File: " + file.filename)
+    
\ No newline at end of file
diff --git a/tools/scripts/CodeChecker/main.py b/tools/scripts/CodeChecker/main.py
new file mode 100644 (file)
index 0000000..29352c6
--- /dev/null
@@ -0,0 +1,23 @@
+import sys
+from BuildLog import BuildLog
+from PRManager import PRManager
+
+logPath = "./build.log"
+
+if __name__ == "__main__":
+    if len(sys.argv) == 1:
+        print("Execute with a PR number")
+        print(" ~$ python main.py [PR Number]")
+        exit(1)
+    logs = BuildLog(logPath)
+    pr = PRManager(int(sys.argv[1]))
+    warningsInFile = []
+    for file in pr.changedFiles:
+        warningsInFile = [warning for warning in logs.warnings if file.filename.endswith(warning[logs.FILE])]
+
+        for diffLine in pr.fileDiffHunkPairs[file]:
+            for warning in warningsInFile:
+                if (diffLine[0]) <= warning[BuildLog.LINE_NUMBER] and warning[BuildLog.LINE_NUMBER] <= (diffLine[0] + diffLine[1]):
+                    print("{}, Warning on line {}! -> ".format(file.filename, warning[BuildLog.LINE_NUMBER]) + warning[BuildLog.MESSAGE])
+                    pr.CreateReviewComment(file, warning[BuildLog.LINE_NUMBER], warning[BuildLog.MESSAGE])
+