Example #1
0
class TestCoder(unittest.TestCase):
    def setUp(self):
        # Init coder
        print("Initializing coder...")
        self.checker = self.checkerList[self.checkerIndex]
        self.dictionary = Dictionary(self.checker)
        self.coder = Coder(self.dictionary)
        # Load all data from DB
        print("Fetching data from database...")
        self.allData = self.db.getFixDataForChecker(self.checker)
        self.allDataLen = len(self.allData)
        print("Done, fetched {0} records".format(self.allDataLen))

    def tearDown(self):
        self.checkerIndex += 1

    @classmethod
    def setUpClass(self):
        print("Starting up...")
        self.db = CFDatabase(config.getCfDbFile())
        self.checkers = Checkers()
        self.checkerList = ['deadcode.DeadStores']
        self.checkerIndex = 0

    def testDeadcodeDeadStores(self):
        self.assertTrue(self.allDataLen > 0, msg="No data found")

        # Encode all data
        print("Testing encoding")
        i = 0
        while i < self.allDataLen:
            checkerInfo = self.checkers.extractTokensForChecker(
                self.checker, self.allData[i][4])
            encodedBugData, initialUnkList = self.coder.encode(
                self.allData[i][1], checkerData=checkerInfo)
            encodedFixData, finalUnkList = self.coder.encode(
                self.allData[i][2], unkList=initialUnkList, reverse=False)
            if -1 in encodedBugData:
                print(
                    "{0}: [{2} - {3} ({1})] Some tokens were not parsed (bug), ignoring (lenUnk = {1})"
                    .format(i + 1, len(finalUnkList), len(encodedBugData),
                            len(encodedFixData)))
            elif -1 in encodedFixData:
                print(
                    "{0}: [{2} - {3} ({1})] Some tokens were not parsed (fix), ignoring (lenUnk = {1})"
                    .format(i + 1, len(finalUnkList), len(encodedBugData),
                            len(encodedFixData)))
            else:
                print("{0}: [{2} - {3} ({1})] Done (lenUnk = {1})".format(
                    i + 1, len(finalUnkList), len(encodedBugData),
                    len(encodedFixData)))
                textBug = self.coder.decode(encodedBugData, finalUnkList, True)
                textFix = self.coder.decode(encodedFixData, finalUnkList)
                self.assertEqual(textBug, self.allData[i][1])
                self.assertEqual(textFix, self.allData[i][2])
            i += 1

        print("All done.")
Example #2
0
class Predictor():
    def __init__(self):
        self.vcs = GitProvider(config.getRepoDir())
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.checkers = Checkers()
        self.loadCommitList()

    def loadCommitList(self):
        self.commits = self.vcs.getAllVersions(config.getBranch())
        self.currentCommitIndex = 0

    def convertFilePathToRepoRelativePath(self, path):
        return os.path.relpath(path, config.getRepoDir())

    def getDiffResolvedIds(self):
        resolved = self.codeChecker.diffResolved(config.getCcRunName(),
                                                 config.getTmpDir(), self.ccdb)
        ids = []
        for bug in resolved:
            ids.append(bug['reportId'])
        return ids

    def predict(self, id, checker):
        # Load all bugs
        print("Loading bug data...")
        ids = []
        if id == -1:
            bugs = self.ccdb.getAllBugsForChecker(checker)
            ids = [x[0] for x in bugs]
        else:
            ids.append(id)

        # Loading model
        print("Loading model...")
        model = load_model(config.cfModelFilenameFormat.format(checker))
        model.summary()
        vLabels = ['NOT OK', 'OK', 'Skipped']

        # Initialize coder
        print("Initializing coder...")
        self.dictionary = Dictionary(checker)
        self.coder = Coder(self.dictionary)
        self.totalDictionaryLength = self.dictionary.length()

        # Predicting
        print("Starting predictions...")
        for i in ids:
            allData = self.ccdb.getBugData(i)
            if allData.getChecker(
            ) not in globals.availableCheckers or allData.getChecker(
            ) != checker:
                print("Bug #{0} - checker not supported".format(i))
            else:
                # Load extra tokens from checker message
                checkerInfo = self.checkers.extractTokensForChecker(
                    allData.getChecker(), allData.getMessage())
                # Retrieve code fragment with bug
                fileRelativePath = self.convertFilePathToRepoRelativePath(
                    allData.getFile())
                fullCodeWithBug = self.vcs.getFileContents(
                    fileRelativePath, self.commits[self.currentCommitIndex])
                extractor = CodeExtractor(allData)
                extractor.loadCodeFromText(fullCodeWithBug)
                extractor.extractBugCode()
                bugCodeFragment = extractor.getBugCodeFragment()
                fixCodeFragment = ''
                # Encode it
                encodedBugData, initialUnkList = self.coder.encode(
                    bugCodeFragment, checkerData=checkerInfo)
                # Convert to one-hot
                MODEL_X_MAX_LEN = model.get_layer(index=0).input_shape[1]
                if len(encodedBugData) > MODEL_X_MAX_LEN:
                    print(
                        "Bug #{0} - Code too big for model, ignored".format(i))
                    continue
                elif id == -1:
                    print("Bug #{0} - Good to go".format(i))
                    continue
                noZerosToPad = MODEL_X_MAX_LEN - len(encodedBugData)
                if noZerosToPad > 0:
                    encodedBugData = self.coder.applyPadding(
                        encodedBugData, noZerosToPad)
                X = np.zeros((1, MODEL_X_MAX_LEN, self.totalDictionaryLength))
                X[0] = self.coder.convertToOneHot(
                    encodedBugData,
                    np.zeros((MODEL_X_MAX_LEN, self.totalDictionaryLength)))
                # Predict and convert from one-hot
                Y = self.coder.convertFromOneHot(model.predict(X)[0])
                print(Y)
                # Decode
                Y = self.coder.removePadding(Y)
                fixCodeFragment = self.coder.decode(Y, initialUnkList)

                #Verify?
                vStatus = 2
                if config.cfVerifyPrediction:
                    # Apply fix in source code file
                    extractor.applyFix(fixCodeFragment)
                    extractor.saveToFile(allData.getFile())
                    # Run CodeChecker and analyze code
                    self.codeChecker.check(True)
                    resolvedIds = self.getDiffResolvedIds()
                    # Check if ID is resolved in tmp folder
                    isFixed = i in resolvedIds
                    # Set vStatus accordingly
                    if isFixed:
                        vStatus = 1
                    else:
                        vStatus = 0
                #Print
                print("Bug #{0} - summary".format(i))
                print("== Code fragment with bug ==")
                print(bugCodeFragment)
                print("== Suggested fix ==")
                print(fixCodeFragment)
                print("Verification: {0}".format(vLabels[vStatus]))
                a = ' '
                while a != 'y' and a != 'n':
                    a = input("Apply fix? (y/n): ")
                if a == 'y':
                    if not config.cfVerifyPrediction:
                        # Apply fix in source code file
                        extractor.applyFix(fixCodeFragment)
                        extractor.saveToFile(allData.getFile())
                elif config.cfVerifyPrediction:
                    # Revert file contents
                    self.vcs.checkout(self.commits[self.currentCommitIndex])
                print('Done')
        print("All done, exiting...")
Example #3
0
class Verifier():
    def __init__(self):
        self.vcs = GitProvider(config.getRepoDir())
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.checkers = Checkers()

    def convertFilePathToRepoRelativePath(self, path):
        return os.path.relpath(path, config.getRepoDir())

    def getDiffResolvedIds(self):
        resolved = self.codeChecker.diffResolved(config.getCcRunName(), config.getTmpDir(), self.ccdb)
        ids = []
        for bug in resolved:
            ids.append(bug['reportId'])
        return ids
    
    def getBugDataFromDiff(self, obj):
        return BugData(int(obj['location']['line']), int(obj['location']['line']), obj['location']['file_name'], obj['check_name'], 'New', obj['description'], int(obj['location']['line']), None)

    def getDiffNew(self):
        new = self.codeChecker.diffNew(config.getCcRunName(), config.getTmpDir(), self.ccdb)
        ids = []
        for bug in new:
            ids.append(self.getBugDataFromDiff(bug))
        return ids
    
    def isBugDataEqual(self, b1, b2):
        if b1.getLine() != b2.getLine():
            return False
        if b1.getChecker() != b2.getChecker():
            return False
        if b1.getMessage() != b2.getMessage():
            return False
        if b1.getFile() != b2.getFile():
            return False
        if b1.getStatus() != b2.getStatus():
            return False
        if b1.getReviewStatus() != b2.getReviewStatus():
            return False
        return True
    
    def displaySuggestions(self, suggestions):
        statuses = ['Negative', 'Positive', 'Skipped']
        for s in suggestions:
            print("File: {2}, L{0}, Type: {1}".format(s.bug.getLine(), s.bug.getChecker(), s.file))
            print("Verification status: {0}".format(statuses[s.verificationStatus]))
            if s.verificationStatus in [1, 2]:
                print("Code fragment with bug: \n{0}".format(s.bugCode))
                print("Suggested code fragment for replacement: \n{0}".format(s.fixCode))
    
    def applyValidFixes(self, suggestions, files):
        for f in files:
            bugs = []
            for s in suggestions:
                if s.file == f and s.verificationStatus in [1, 2]:
                    bugs.append(s)
            bugs.sort(key=lambda x: x.bug.getLine(), reverse=True)
            for b in bugs:
                print("File: {2}, L{0}, Type: {1}... ".format(b.bug.getLine(), b.bug.getChecker(), s.file), end='')
                self.applyFix(b)
                print("Applied")
            self.vcs.applyChangeForFile(f)
    
    def applyFix(self, s):
        extractor = CodeExtractor(s.bug)
        extractor.loadCodeFromFile()
        extractor.extractBugCode()
        extractor.applyFix(s.fixCode)
        extractor.saveToFile(s.bug.getFile())
    
    def main(self):
        # Do analysis
        shutil.rmtree(config.getTmpDir())
        self.codeChecker.check(True)

        # Diff new
        newBugs = self.getDiffNew()

        if len(newBugs) < 1:
            print('No new bugs introduced, commit is accepted!')
            return
        
        print("New bugs found! Count: {0}. Attempting repairs...".format(len(newBugs)))

        # Load models
        models = {}
        for checker in globals.availableCheckers:
            models[checker] = load_model(config.cfModelFilenameFormat.format(checker))

        # Load all content from files having new
        files = set([self.convertFilePathToRepoRelativePath(x.getFile()) for x in newBugs])
        fileContents = {}
        for f in files:
            fn = config.getRepoDir() + f
            with open(fn, 'r') as fh:
                fileContents[f] = ''.join(fh.readlines())

        # For each file sort by bug line desc
        suggestions = []
        validSuggestions = 0
        for f in files:
            bugs = [x for x in newBugs if self.convertFilePathToRepoRelativePath(x.getFile()) == f]
            bugs.sort(key=lambda x: x.getLine(), reverse=True)
            print("=== File: {0} ===".format(f))
            # For each bug get a suggestion and test it
            for b in bugs:
                print("L{0}, Type: {1}".format(b.getLine(), b.getChecker()))
                # Prepare useful data
                dictionary = Dictionary(b.getChecker())
                coder = Coder(dictionary)
                totalDictionaryLength = dictionary.length()
                # Prepare and extract bug fragment
                checkerInfo = self.checkers.extractTokensForChecker(b.getChecker(), b.getMessage())
                extractor = CodeExtractor(b)
                extractor.loadCodeFromText(fileContents[f])
                extractor.extractBugCode()
                bugCodeFragment = extractor.getBugCodeFragment()
                fixCodeFragment = ''
                # Encode it
                encodedBugData, initialUnkList = coder.encode(bugCodeFragment, checkerData = checkerInfo)
                # Convert to one-hot
                MODEL_X_MAX_LEN = models[b.getChecker()].get_layer(index = 0).input_shape[1]

                if len(encodedBugData) > MODEL_X_MAX_LEN:
                    print("Ignored: Code too big for model")
                    continue

                noZerosToPad = MODEL_X_MAX_LEN - len(encodedBugData)
                if noZerosToPad > 0:
                    encodedBugData = coder.applyPadding(encodedBugData, noZerosToPad)
                X = np.zeros((1, MODEL_X_MAX_LEN, totalDictionaryLength))
                X[0] = coder.convertToOneHot(encodedBugData, np.zeros((MODEL_X_MAX_LEN, totalDictionaryLength)))
                # Predict and convert from one-hot
                Y = coder.convertFromOneHot(models[b.getChecker()].predict(X)[0])
                Y = coder.removePadding(Y)
                # Decode
                fixCodeFragment = coder.decode(Y, initialUnkList)[:-1]
                
                #Verify?
                vStatus = 2
                if config.cfVerifyPrediction:
                    # Apply fix in source code file
                    extractor.applyFix(fixCodeFragment)
                    extractor.saveToFile(b.getFile())
                    # Run CodeChecker and analyze code
                    shutil.rmtree(config.getTmpDir())
                    compilationLog = self.codeChecker.check(True)
                    newBugsAfterFix = self.getDiffNew()
                    # Check if ID is resolved in tmp folder
                    isFixed = 'Build failed' not in compilationLog
                    for nb in newBugsAfterFix:
                        if self.isBugDataEqual(b, nb):
                            isFixed = False
                    # Set vStatus accordingly
                    if isFixed:
                        vStatus = 1
                    else:
                        vStatus = 0
                    # Revert file
                    extractor.loadCodeFromText(fileContents[f])
                    extractor.saveToFile(b.getFile())
                if vStatus == 0:
                    print("Verification: Negative, cannot be applied")
                elif vStatus == 1:
                    print("Verification: Positive, can be applied")
                    validSuggestions += 1
                elif vStatus == 2:
                    print("Verification: Skipped")
                    validSuggestions += 1
                sugg = SuggestionData(f, b, bugCodeFragment, fixCodeFragment, vStatus)
                suggestions.append(sugg)
        print("Valid suggestions prepared for {0} / {1} bugs.".format(validSuggestions, len(newBugs)))

        if validSuggestions > 0:
            print("Apply valid suggestions (a), display them (d), ignore them (i) or abort commit (q)?")
            apply = False
            choice = True
            while choice:
                c = sys.stdin.read(1)
                if c == 'a':
                    apply = True
                    choice = False
                    print("Applying fixes...")
                elif c == 'i':
                    choice = False
                    print("Fixes ignored...")
                elif c == 'd':
                    self.displaySuggestions(suggestions)
                    print("Apply valid suggestions (a), ignore them (i) or abort commit (q)?")
                elif c == 'q':
                    print("Aborting commit...")
                    sys.exit(1)
            if apply:
                self.applyValidFixes(suggestions, files)
                print("Fixes applied!")
        if validSuggestions != len(newBugs):
            print("Unable to fix all bugs, continue with commit (c) or abort (q)?")
            choice = True
            while choice:
                c = sys.stdin.read(1)
                if c == 'c':
                    choice = False
                    print("Continuing...")
                elif c == 'q':
                    print("Aborting commit...")
                    sys.exit(1)
        else:
            print("Bugs corrected, commit is good to go!")
class DictionaryBuilder():
    def __init__(self):
        self.db = CFDatabase(config.getCfDbFile())
        self.lexer = CxxLexer()
        self.checkers = Checkers()

    def build(self, checker):
        # Load all data from DB
        print("Fetching data from database...")
        allData = self.db.getFixDataForChecker(checker)
        allDataLen = len(allData)
        print("Done, fetched {0} records".format(allDataLen))
        if allDataLen < 1:
            print("No data found")
            return

        # Tokenize all code snippets and extract extra tokens from checker's messages
        # Labelize all tokens existing only in fixed code (added data)
        # Labelize all tokens appearing more than X times
        # Labelize all C++ STL names (namespaces, constants, defines, variables, functions, headers, numeric literals)
        # Labelize all UNK token indexes
        print("Converting to tokens...")
        tokens = deque()
        tokensLen = 0
        labels = {}
        i = 0
        tokensLen = 0

        minTokens1Len = 9999
        minTokens2Len = 9999
        maxTokens1Len = 0
        maxTokens2Len = 0

        uniqTokenIDs = {}
        for tid in range(globals.firstAvailableToken):
            uniqTokenIDs[tid] = 0
        uniqTokenIDs[0] = 1  # T_ZERO
        uniqTokenIDs[349] = 1  # T_SOS
        uniqTokenIDs[351] = 1  # T_UNK

        while i < allDataLen:
            # Tokenize
            tokens1 = self.lexer.tokenize(allData[i][1])
            tokens2 = self.lexer.tokenize(allData[i][2])
            extra = self.checkers.extractTokensForChecker(
                checker, allData[i][4])
            newTokens = []

            # Extract new tokens
            for token2 in tokens2:
                matchFound = False
                for token1 in tokens1:
                    if token1['token'] == token2['token'] and token1[
                            'has_value'] == token2['has_value']:
                        if token1['has_value']:
                            if token1['value'] == token2['value']:
                                matchFound = True
                        else:
                            matchFound = True
                if not matchFound:
                    newTokens.append(token2)
            tokens1Len = len(tokens1)
            tokens2Len = len(tokens2)

            # Statistics
            if tokens1Len < minTokens1Len:
                minTokens1Len = tokens1Len
            if tokens2Len < minTokens2Len:
                minTokens2Len = tokens2Len
            if tokens1Len > maxTokens1Len:
                maxTokens1Len = tokens1Len
            if tokens2Len > maxTokens2Len:
                maxTokens2Len = tokens2Len

            # Count occurrences of each label
            allTokens = tokens1 + tokens2 + extra
            for token in allTokens:
                value = globals.emptyValue
                if token['has_value']:
                    value = token['value']
                if value in labels:
                    labels[value] += 1
                else:
                    labels[value] = 1
                uniqTokenIDs[int(token['token'])] += 1
                tokensLen += 1
            if len(newTokens) > 0:
                tokens.append(newTokens)
            i += 1
            print('Done {0}, processed {1} tokens ({2}/{3}/{4}/{5})'.format(
                i, len(allTokens), tokens1Len, tokens2Len, len(extra),
                len(newTokens)),
                  file=sys.stderr)
        print("Done, converted {0} tokens".format(tokensLen))

        # Labelizing
        labelDb = [globals.emptyValue]
        # UNK
        print("Adding UNK token labels")
        for i in range(config.cfNoOfUnkTokens):
            labelDb.append("UNK_{0}".format(i))
        print("Done, current label DB has {0} entries".format(len(labelDb)))

        # Common occurrences
        print("Filtering labels, selecting only those with > {0} occurrences".
              format(config.cfLabelThreshold))
        for key in labels.keys():
            if labels[key] > config.cfLabelThreshold:
                labelDb.append(key)
        print("Done, current label DB has {0} entries".format(len(labelDb)))

        # New tokens in fixed code
        print("Filtering labels, selecting only tokens introduced with fix")
        for entry in tokens:
            for token in entry:
                if token['has_value']:
                    labelDb.append(token['value'])
        print("Done, current label DB has {0} entries".format(len(labelDb)))

        # STL part

        # Token IDs
        for i in range(globals.firstAvailableToken):
            if uniqTokenIDs[i] > 0:
                labelDb.append("T_{0}".format(i))

        # Printout
        print("Uniqueing labels")
        labelsUnique = list(set(labelDb))
        print("Done, current label DB has {0} entries".format(
            len(labelsUnique)))
        print("Data set info")
        print("Min no of tokens (bug): {0}".format(minTokens1Len))
        print("Min no of tokens (fix): {0}".format(minTokens2Len))
        print("Max no of tokens (bug): {0}".format(maxTokens1Len))
        print("Max no of tokens (fix): {0}".format(maxTokens2Len))
        print("Extracted labels:")
        print(labelsUnique)
        print("Token uses:")
        for i in range(globals.firstAvailableToken):
            if uniqTokenIDs[i] > 0:
                print("{0}: {1}".format(i, uniqTokenIDs[i]))

        # Save to file
        print("Writing to dictionary file")
        with open(config.cfDictFilenameFormat.format(checker), "w") as f:
            f.write(json.dumps(labelsUnique))
        print("Done, exiting...")
Example #5
0
class LearningDataBuilder():
    def __init__(self):
        self.db = CFDatabase(config.getCfDbFile())
        self.checkers = Checkers()

    def build(self, checker):
        # Initialize coder
        print("Initializing coder...")
        self.dictionary = Dictionary(checker)
        self.coder = Coder(self.dictionary)

        # Load all data from DB
        print("Fetching data from database...")
        allData = self.db.getFixDataForChecker(checker)
        allDataLen = len(allData)
        print("Done, fetched {0} records".format(allDataLen))
        if allDataLen < 1:
            print("No data found")
            return

        # Encode all data
        print("Encoding all data and writing to output file...")
        i = 0
        (maxBug, maxFix,
         maxUnk) = self.checkers.getModelStatsForChecker(checker)
        with open(config.cfTrainFilenameFormat.format(checker), 'w') as f:
            while i < allDataLen:
                checkerInfo = self.checkers.extractTokensForChecker(
                    checker, allData[i][4])
                encodedBugData, initialUnkList = self.coder.encode(
                    allData[i][1], checkerData=checkerInfo)
                encodedFixData, finalUnkList = self.coder.encode(
                    allData[i][2], unkList=initialUnkList, reverse=False)
                if -1 in encodedBugData:
                    print(
                        "{0}: [{2} - {3} ({1})] Some tokens were not parsed (bug), ignoring (lenUnk = {1})"
                        .format(i + 1, len(finalUnkList), len(encodedBugData),
                                len(encodedFixData)))
                elif -1 in encodedFixData:
                    print(
                        "{0}: [{2} - {3} ({1})] Some tokens were not parsed (fix), ignoring (lenUnk = {1})"
                        .format(i + 1, len(finalUnkList), len(encodedBugData),
                                len(encodedFixData)))
                elif len(encodedBugData) > maxBug or len(
                        encodedFixData) > maxFix or len(finalUnkList) > maxUnk:
                    print(
                        "{0}: [{2} - {3} ({1})] Some tokens were not parsed (lengths), ignoring (lenUnk = {1})"
                        .format(i + 1, len(finalUnkList), len(encodedBugData),
                                len(encodedFixData)))
                else:
                    print("{0}: [{2} - {3} ({1})] Done (lenUnk = {1})".format(
                        i + 1, len(finalUnkList), len(encodedBugData),
                        len(encodedFixData)))
                    f.write(
                        json.dumps({
                            'x': encodedBugData,
                            'y': encodedFixData
                        }) + '\n')

                i += 1
                print('Done {0}'.format(i), file=sys.stderr)

        print("All done, exiting...")
Example #6
0
class FixTautOORCmp():
    def __init__(self):
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.code = []
        self.checkers = Checkers()

    def loadCodeFromFile(self):
        with open(self.bugData.getFile(), 'r') as file:
            code = file.readlines()
            self.code = []
            for line in code:
                self.code.append(line.replace("\r\n", "\n"))
            """
            code = file.read()
            noCrLf = code.count("\r\n")
            noCr = code.count("\r") - noCrLf
            noLf = code.count("\n") - noCrLf
            if noCrLf > noCr:
                if noCrLf > noLf:
                    self.lineEnding = "\r\n"
                else:
                    self.lineEnding = "\n"
            else:
                if noCr > noLf:
                    self.lineEnding = "\r"
                else:
                    self.lineEnding = "\n"
            self.code = code.split(self.lineEnding)
            """

    def saveCodeToFile(self):
        with open(self.bugData.getFile(), 'w') as file:
            #file.write(self.lineEnding.join(self.code))
            file.writelines(self.code)

    def findMatchingDefine(self, value):
        patValue = '({0})'
        patName = '[ \t]([0-9a-zA-Z_]+)[ \t]'
        for line in self.code:
            if line[:7] == '#define':
                if re.search(patValue.format(value), line):
                    return re.search(patName, line).group(1)
        return None

    def fix(self, file):
        fileData = self.ccdb.getFileData(file)
        print(fileData)
        bugs = self.ccdb.getAllBugsForChecker(
            'clang-diagnostic-tautological-constant-out-of-range-compare')
        lines = []
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() not in lines:
                    self.loadCodeFromFile()

                    tokens = self.checkers.extractTokensForChecker(
                        'clang-diagnostic-tautological-constant-out-of-range-compare',
                        self.bugData.getMessage())
                    line = self.code[self.bugData.getLine() - 1]
                    pat = "\([^\(]*{0}\)".format(tokens[0]['value'])
                    match = re.search(pat, line)
                    if match is None:
                        pat = "\([^\(]*{0}\)".format(
                            self.findMatchingDefine(tokens[0]['value']))
                        match = re.search(pat, line)
                    match = match.group(0)
                    newLine = line.replace(match,
                                           '({0})'.format(tokens[1]['value']))
                    self.code[self.bugData.getLine() - 1] = newLine

                    self.saveCodeToFile()
                    lines = lines + list(
                        range((self.bugData.getLine() - 11),
                              (self.bugData.getLine() + 10)))
                    print("Passed")
                    print(self.bugData.getLine())
                    pass
                else:
                    print("Dismissed")
                    print(self.bugData.getLine())
                    pass
class FixTautOORCmp():
    def __init__(self):
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.code = []
        self.checkers = Checkers()

    def loadCodeFromFile(self):
        with open(self.bugData.getFile(), 'r') as file:
            code = file.readlines()
            self.code = []
            for line in code:
                self.code.append(line.replace("\r\n", "\n"))

    def saveCodeToFile(self):
        with open(self.bugData.getFile(), 'w') as file:
           #file.write(self.lineEnding.join(self.code))
           file.writelines(self.code)
    
    def findMatchingDefine(self, value):
        patValue = '({0})'
        patName = '[ \t]([0-9a-zA-Z_]+)[ \t]'
        for line in self.code:
            if line[:7] == '#define':
                if re.search(patValue.format(value), line):
                    return re.search(patName, line).group(1)
        return None
    
    def fix(self, file):
        fileData = self.ccdb.getFileData(file)
        print(fileData)
        bugs = self.ccdb.getAllBugsForChecker('clang-diagnostic-constant-conversion')
        lines = []
        linesSingle = {}
        linesToSuppress = []
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() in linesSingle:
                    linesSingle[self.bugData.getLine()] += 1
                else:
                    linesSingle[self.bugData.getLine()] = 1
        for k in linesSingle:
            if linesSingle[k] > 5:
                linesToSuppress.append(k)
        inserts = 0
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() not in lines:
                    self.loadCodeFromFile()

                    if self.bugData.getLine() not in linesToSuppress:
                        tokens = self.checkers.extractTokensForChecker('clang-diagnostic-constant-conversion', self.bugData.getMessage())
                        test = tokens
                        line = self.code[self.bugData.getLine() - 1 + inserts]
                        newLine = line.replace(tokens[0]['value'], '({0}){1}'.format(tokens[1]['value'], tokens[0]['value']))
                        if line == newLine:
                            tokens[0]['value'] = self.findMatchingDefine(tokens[0]['value'])
                            if tokens[0]['value'] is not None:
                                newLine = line.replace(tokens[0]['value'], '({0}){1}'.format(tokens[1]['value'], tokens[0]['value']))
                        if line == newLine:
                            s = re.search('= (.*);', line)
                            expr = s.group(1)
                            newLine = line.replace(expr, '({0})({1})'.format(tokens[1]['value'], expr))
                        self.code[self.bugData.getLine() - 1 + inserts] = newLine
                    else:
                        line = self.code[self.bugData.getLine() - 1 + inserts]
                        self.code[self.bugData.getLine() - 1 + inserts] = '// codechecker_intentional [clang-diagnostic-constant-conversion] Suppress\n{0}'.format(line)
                        inserts += 1

                    self.saveCodeToFile()
                    lines = lines + list(range((self.bugData.getLine() - 11), (self.bugData.getLine() + 10)))
                    
                    print("Passed, suppressed: {0}".format(self.bugData.getLine() in linesToSuppress))
                    print(self.bugData.getLine())
                    pass
                else:
                    print("Dismissed")
                    print(self.bugData.getLine())
                    pass