Пример #1
0
 def __init__(self,
              mainFilePath,
              mainFunction,
              buildSolutionCmd,
              keepBackupFiles=False):
     '''
     Constructor.
     '''
     self.buildSolutionCmd = buildSolutionCmd
     self.keepBackupFiles = keepBackupFiles
     self.sourceCodeParser = SourceCodeParser(
         ProgramExecution.Languages.C_PLUS_PLUS, mainFilePath, mainFunction)
     self.filesToAnnotate = []
     self.functionsToAnnotate = []
     self.classesToAnnotate = []
     self.mainFilePath = mainFilePath
     self.dumpFileName = ""
     self.oldFiles = []
 def __init__(self, mainFilePath, mainFunction, buildSolutionCmd, keepBackupFiles = False):
     '''
     Constructor.
     '''
     self.buildSolutionCmd = buildSolutionCmd
     self.keepBackupFiles = keepBackupFiles
     self.sourceCodeParser = SourceCodeParser(ProgramExecution.Languages.C_PLUS_PLUS, mainFilePath, mainFunction)
     self.filesToAnnotate = []
     self.functionsToAnnotate = []
     self.classesToAnnotate = []
     self.mainFilePath = mainFilePath
     self.dumpFileName = ""
     self.oldFiles = []
class CppAnnotator:
    '''
    Annotator for C++ classes. It's the C++ counterpart of annotator.Annotator.
    As Annotator, it follows the "with" syntax (RAII idiom for Python):
    inside the "with" scope, the C++ functions are annotated to
    generate a call-graph database. This is the code flow to get this effect:
    
    * Create a CppAnnotator.
    * call annotateMainFile():
        * this backs up the main file name, to be annotated later.
    * call annotateFunctions() or similar annotation functions:
        * this saves these functions in a container, to be annotated later.
    * with myCppAnnotator... this calls __enter__(), where:
        * annotations actually take place:
          * main file and functions from the containers are modified,
          saving a backup for each one of them.
        * build the compiler solution. This generates a new EXE.
    * call the EXE inside the with (for example, using os.system()).
        * this EXE will generate the annotations (remember the annotations and build above).
    * exit the with clause:
        * restore the backups for all the modified files.
        * "touch" the files, to force the compiler to build them.
        * build the solution. This generates an EXE without annotations.
    '''
    activeAnnotators = False
    
    
    ##
    # @param self The CppAnnotator instance to construct.
    # @param mainFilePath The program's main file path.
    # @param mainFunction The program's main function.
    # @param buildSolutionCmd Command to build the solution.
    # @param keepBackupFiles Keep annotated files after restoring the original (at the __exit__() function).
    def __init__(self, mainFilePath, mainFunction, buildSolutionCmd, keepBackupFiles = False):
        '''
        Constructor.
        '''
        self.buildSolutionCmd = buildSolutionCmd
        self.keepBackupFiles = keepBackupFiles
        self.sourceCodeParser = SourceCodeParser(ProgramExecution.Languages.C_PLUS_PLUS, mainFilePath, mainFunction)
        self.filesToAnnotate = []
        self.functionsToAnnotate = []
        self.classesToAnnotate = []
        self.mainFilePath = mainFilePath
        self.dumpFileName = ""
        self.oldFiles = []

    # @param self The CppAnnotator instance.
    # @param dumpFileName File where the call graph database will be dumped.
    def annotateMainFile(self, dumpFileName ):
        '''
        Mark main file to be annotated at __enter__().
        '''
        self.dumpFileName = dumpFileName

    ##
    # @param self The CppAnnotator instance.
    # @param originalFileName File name of the original (unprocessed) file name.
    # @param headerToInclude Header to include.
    def annotateFile(self, originalFileName, headerToInclude):
        '''
        Mark a C++ source file to be annotated __enter__().
        '''
        self.filesToAnnotate.append((originalFileName, headerToInclude))
 
    ##
    # @param self The CppAnnotator instance.
    # @param originalFileName File name of the original (unprocessed) file name.
    # @param headerToInclude Header to include.
    # @param functionNames Function names to filter.
    def annotateFunctions(self, originalFileName, headerToInclude, functionNames = []):
        '''
        Mark a C++ source file to be annotated __enter__(),
        filtering by functions.
        '''
        self.functionsToAnnotate.append((originalFileName, headerToInclude, functionNames))

    ##
    # @param self The CppAnnotator instance.
    # @param originalFileName File name of the original (unprocessed) file name.
    # @param headerToInclude Header to include.
    # @param classNames Class names to filter.
    def annotateClasses(self, originalFileName, headerToInclude, classNames = []):
        '''
        Mark a C++ source file to be annotated __enter__(),
        filtering by classes.
        '''        
        self.classesToAnnotate.append((originalFileName, headerToInclude, classNames))

    ##
    # @param self The CppAnnotator instance.
    def __enter__(self):
        '''
        Entry point for the "with" sentence. It annotates the files, and builds the solution.
        The new EXE will generate the Json database.
        '''
        if CppAnnotator.activeAnnotators:
            #Limit instances number to 1
            raise RuntimeError('Cpp annotators number should limit to 1.')
        CppAnnotator.activeAnnotators = True
        self._resetForNewAnnotations()
        try:
            #Backup main old file, in order to restore it later
            mainBackupFileName = getBackupFileName(self.mainFilePath)
            shutil.copyfile(self.mainFilePath, mainBackupFileName)
            self.oldFiles.append(self.mainFilePath)
            self.sourceCodeParser.annotateMainFile(self.dumpFileName)
            
            #Merge 3 containers in one, and iterate it
            originalFileNameToInfo = {}
            for myFile in self.filesToAnnotate:
                originalFileName, headerToInclude = myFile
                myInfo = [headerToInclude, None, None]
                originalFileNameToInfo[originalFileName] = myInfo

            for myClass in self.classesToAnnotate:
                originalFileName, headerToInclude, classNames = myClass
                if originalFileNameToInfo.has_key(originalFileName):
                    myInfo = originalFileNameToInfo[originalFileName]
                else:
                    myInfo = [headerToInclude, None, None]
                    originalFileNameToInfo[originalFileName] = myInfo
                myInfo[1] = classNames
            
            for myFunction in self.functionsToAnnotate:
                originalFileName, headerToInclude, functionNames = tuple(myFunction)
                if originalFileNameToInfo.has_key(originalFileName):
                    myInfo = originalFileNameToInfo[originalFileName]
                else:
                    myInfo = [headerToInclude, None, None]
                    originalFileNameToInfo[originalFileName] = myInfo
                myInfo[2] = functionNames
            
            for originalFileName, fileInfo in originalFileNameToInfo.items():
                headerToInclude, classNames, functionNames = fileInfo 
                #Backup old files, in order to restore them later
                backupFileName = getBackupFileName(originalFileName)
                shutil.copyfile(originalFileName, backupFileName)
                self.oldFiles.append(originalFileName)
                if classNames is None and functionNames is None:
                    self.sourceCodeParser.annotateFile(backupFileName, originalFileName, headerToInclude)
                else:
                    if classNames is not None:
                        self.sourceCodeParser.annotateCppClasses(backupFileName, originalFileName, headerToInclude, classNames)
                    if functionNames is not None and classNames is None:
                        self.sourceCodeParser.annotateCppFunctions(backupFileName, originalFileName, headerToInclude, functionNames)
            self.buildSolution_()
            return self
        except Exception, e:
            print str(e)
            self.restoreSourcesForSolution_()
            raise e
Пример #4
0
class CppAnnotator:
    '''
    Annotator for C++ classes. It's the C++ counterpart of annotator.Annotator.
    As Annotator, it follows the "with" syntax (RAII idiom for Python):
    inside the "with" scope, the C++ functions are annotated to
    generate a call-graph database. This is the code flow to get this effect:
    
    * Create a CppAnnotator.
    * call annotateMainFile():
        * this backs up the main file name, to be annotated later.
    * call annotateFunctions() or similar annotation functions:
        * this saves these functions in a container, to be annotated later.
    * with myCppAnnotator... this calls __enter__(), where:
        * annotations actually take place:
          * main file and functions from the containers are modified,
          saving a backup for each one of them.
        * build the compiler solution. This generates a new EXE.
    * call the EXE inside the with (for example, using os.system()).
        * this EXE will generate the annotations (remember the annotations and build above).
    * exit the with clause:
        * restore the backups for all the modified files.
        * "touch" the files, to force the compiler to build them.
        * build the solution. This generates an EXE without annotations.
    '''
    activeAnnotators = False

    ##
    # @param self The CppAnnotator instance to construct.
    # @param mainFilePath The program's main file path.
    # @param mainFunction The program's main function.
    # @param buildSolutionCmd Command to build the solution.
    # @param keepBackupFiles Keep annotated files after restoring the original (at the __exit__() function).
    def __init__(self,
                 mainFilePath,
                 mainFunction,
                 buildSolutionCmd,
                 keepBackupFiles=False):
        '''
        Constructor.
        '''
        self.buildSolutionCmd = buildSolutionCmd
        self.keepBackupFiles = keepBackupFiles
        self.sourceCodeParser = SourceCodeParser(
            ProgramExecution.Languages.C_PLUS_PLUS, mainFilePath, mainFunction)
        self.filesToAnnotate = []
        self.functionsToAnnotate = []
        self.classesToAnnotate = []
        self.mainFilePath = mainFilePath
        self.dumpFileName = ""
        self.oldFiles = []

    # @param self The CppAnnotator instance.
    # @param dumpFileName File where the call graph database will be dumped.
    def annotateMainFile(self, dumpFileName):
        '''
        Mark main file to be annotated at __enter__().
        '''
        self.dumpFileName = dumpFileName

    ##
    # @param self The CppAnnotator instance.
    # @param originalFileName File name of the original (unprocessed) file name.
    # @param headerToInclude Header to include.
    def annotateFile(self, originalFileName, headerToInclude):
        '''
        Mark a C++ source file to be annotated __enter__().
        '''
        self.filesToAnnotate.append((originalFileName, headerToInclude))

    ##
    # @param self The CppAnnotator instance.
    # @param originalFileName File name of the original (unprocessed) file name.
    # @param headerToInclude Header to include.
    # @param functionNames Function names to filter.
    def annotateFunctions(self,
                          originalFileName,
                          headerToInclude,
                          functionNames=[]):
        '''
        Mark a C++ source file to be annotated __enter__(),
        filtering by functions.
        '''
        self.functionsToAnnotate.append(
            (originalFileName, headerToInclude, functionNames))

    ##
    # @param self The CppAnnotator instance.
    # @param originalFileName File name of the original (unprocessed) file name.
    # @param headerToInclude Header to include.
    # @param classNames Class names to filter.
    def annotateClasses(self,
                        originalFileName,
                        headerToInclude,
                        classNames=[]):
        '''
        Mark a C++ source file to be annotated __enter__(),
        filtering by classes.
        '''
        self.classesToAnnotate.append(
            (originalFileName, headerToInclude, classNames))

    ##
    # @param self The CppAnnotator instance.
    def __enter__(self):
        '''
        Entry point for the "with" sentence. It annotates the files, and builds the solution.
        The new EXE will generate the Json database.
        '''
        if CppAnnotator.activeAnnotators:
            #Limit instances number to 1
            raise RuntimeError('Cpp annotators number should limit to 1.')
        CppAnnotator.activeAnnotators = True
        self._resetForNewAnnotations()
        try:
            #Backup main old file, in order to restore it later
            mainBackupFileName = getBackupFileName(self.mainFilePath)
            shutil.copyfile(self.mainFilePath, mainBackupFileName)
            self.oldFiles.append(self.mainFilePath)
            self.sourceCodeParser.annotateMainFile(self.dumpFileName)

            #Merge 3 containers in one, and iterate it
            originalFileNameToInfo = {}
            for myFile in self.filesToAnnotate:
                originalFileName, headerToInclude = myFile
                myInfo = [headerToInclude, None, None]
                originalFileNameToInfo[originalFileName] = myInfo

            for myClass in self.classesToAnnotate:
                originalFileName, headerToInclude, classNames = myClass
                if originalFileNameToInfo.has_key(originalFileName):
                    myInfo = originalFileNameToInfo[originalFileName]
                else:
                    myInfo = [headerToInclude, None, None]
                    originalFileNameToInfo[originalFileName] = myInfo
                myInfo[1] = classNames

            for myFunction in self.functionsToAnnotate:
                originalFileName, headerToInclude, functionNames = tuple(
                    myFunction)
                if originalFileNameToInfo.has_key(originalFileName):
                    myInfo = originalFileNameToInfo[originalFileName]
                else:
                    myInfo = [headerToInclude, None, None]
                    originalFileNameToInfo[originalFileName] = myInfo
                myInfo[2] = functionNames

            for originalFileName, fileInfo in originalFileNameToInfo.items():
                headerToInclude, classNames, functionNames = fileInfo
                #Backup old files, in order to restore them later
                backupFileName = getBackupFileName(originalFileName)
                shutil.copyfile(originalFileName, backupFileName)
                self.oldFiles.append(originalFileName)
                if classNames is None and functionNames is None:
                    self.sourceCodeParser.annotateFile(backupFileName,
                                                       originalFileName,
                                                       headerToInclude)
                else:
                    if classNames is not None:
                        self.sourceCodeParser.annotateCppClasses(
                            backupFileName, originalFileName, headerToInclude,
                            classNames)
                    if functionNames is not None and classNames is None:
                        self.sourceCodeParser.annotateCppFunctions(
                            backupFileName, originalFileName, headerToInclude,
                            functionNames)
            self.buildSolution_()
            return self
        except Exception, e:
            print str(e)
            self.restoreSourcesForSolution_()
            raise e