Esempio n. 1
0
    def findSymbols(self):
        '''
    Find and lookup symbols including inheritance relations.
    '''

        # grab all js files
        filefinder = JSFileFinder()
        jsfiles = filefinder.run()

        #    jsfiles = ['/chb/users/daniel.haehn/Projects/X/math/matrix.js']

        # .. and loop through them
        for filename in jsfiles:

            # classes for this file
            classes = {}

            with open(filename, 'r') as f:

                # read the whole file
                lines = f.readlines()

            # state switches
            jsdocActive = False
            queryIdentifier = False
            jsdocBuffer = ''

            # class information (use the filename by default)
            classname = os.path.splitext(os.path.split(filename)[1])[0]
            inherits = []
            exports = []

            # symbol information
            type = self.TYPES['undefined']
            privacy = self.PRIVACY['private']  # by default private
            params = []  # store the parameters of functions
            returns = []  # and if the function has a return value

            # forward loop through file
            for line in lines:

                line = line.strip()
                if line:
                    # ignore blank lines

                    # check for GOOGEXPORT
                    if line[0:len(self.GOOGEXPORT)] == self.GOOGEXPORT:
                        exports.append(line[len(self.GOOGEXPORT):].split(',')
                                       [0].strip("'").split('.')[-1])
                        continue

                    # check for JSDOC
                    if line[0:len(self.JSDOCSTART)] == self.JSDOCSTART:
                        # found start of JSDOC
                        jsdocBuffer += line[0:len(self.JSDOCSTART)]
                        jsdocActive = True
                        continue

                    if jsdocActive:
                        # this is part of the JSDOC

                        # remove possible <pre></pre> tags since we don't use them
                        jsdocBuffer += '\n' + line.replace(
                            '<pre>', '').replace('</pre>', '')

                        #
                        # check for special jsdoc tags inside the comments
                        #

                        # @param
                        param = line.find(self.PARAMJSDOC)
                        if param != -1:
                            paramName = line[param +
                                             len(self.PARAMJSDOC):].strip(
                                             ).split(' ')[1]
                            params.append('$' + paramName)

                        # @return
                        return_ = line.find(self.RETURNJSDOC)
                        if return_ != -1:
                            returns.append(True)

                        # @extends
                        extends = line.find(self.EXTENDSJSDOC)
                        if extends != -1:
                            inheritsClass = line[extends +
                                                 len(self.EXTENDSJSDOC
                                                     ):].strip()

                            # strip the namespace
                            inheritsClass = inheritsClass.replace(
                                self.NAMESPACE + '.', '')

                            inherits.append(inheritsClass)

                        # @mixin
                        mixin = line.find(self.MIXINJSDOC)
                        if mixin != -1:
                            inheritsClass = line[mixin +
                                                 len(self.MIXINJSDOC):].strip(
                                                 )

                            # strip the namespace
                            inheritsClass = inheritsClass.replace(
                                self.NAMESPACE + '.', '')

                            inherits.append(inheritsClass)

                    if jsdocActive and line[0:len(self.JSDOCEND
                                                  )] == self.JSDOCEND:
                        # end of JSDOC
                        jsdocActive = False
                        queryIdentifier = True
                        continue

                    if queryIdentifier:
                        # store the Identifier and the corresponding JSDOC

                        identifier = line.split(' ')[0]  # split by blank
                        identifierSplitted = identifier.split(
                            '.')  # split by dot
                        # classname = identifierSplitted[1] # should always be the classname
                        identifier = identifierSplitted[-1]

                        # check for namespace
                        if line[0] != self.NAMESPACE:

                            # check if this is a public property
                            if line[0:4] == self.THIS:

                                # check if the property has a constant name aka. is defined with a string
                                if line[4:6] == "['" or line[4:6] == '["':
                                    # this is a public property property
                                    privacy = 1
                                    # todo set correct identifier

                                type = self.TYPES['property']

                            else:
                                # no namespace so we reset the buffer
                                jsdocBuffer = ''
                                queryIdentifier = False
                                continue

                        elif identifierSplitted[-2] != self.PROTOTYPE:

                            # static method or constructor
                            if jsdocBuffer.find(self.CONSTRUCTORJSDOC) != -1:
                                # this is a constructor
                                type = self.TYPES['constructor']
                                classname = identifier

                                # check if we have parent classes, then update the inheritance table
                                if len(inherits) > 0:
                                    # add to inheritances
                                    if not self.__inheritances.has_key(
                                            classname):
                                        self.__inheritances[classname] = []

                                    self.__inheritances[classname].extend(
                                        inherits)
                                    inherits = []  # reset the inheritances

                                # always add to classes
                                self.__allclasses.append(classname)

                            else:
                                # this is a static method
                                type = self.TYPES['static']

                        else:
                            # a prototype method
                            type = self.TYPES['function']

                            # check for getters/setters
                            if identifier[0:len(self.DEFINEGETTER
                                                )] == self.DEFINEGETTER:
                                # a getter
                                identifier = identifier[len(
                                    self.DEFINEGETTER):].split("'")[1] + '_get'
                                type = self.TYPES['gettersetter']
                                privacy = self.PRIVACY['public']

                            elif identifier[0:len(self.DEFINESETTER
                                                  )] == self.DEFINESETTER:
                                # a setter
                                identifier = identifier[len(
                                    self.DEFINESETTER):].split("'")[1] + '_set'
                                type = self.TYPES['gettersetter']
                                privacy = self.PRIVACY['public']

                        if not classes.has_key(classname):
                            # no symbols for this class yet
                            classes[classname] = {}

                        # grab the subfolder name
                        subfolder = os.path.dirname(filename).split(os.sep)[-1]

                        # ignore toplevel files and also the NAMESPACE declaration
                        if not subfolder == '..' and not classname == self.NAMESPACE:

                            # check if we have already files from this subfolder
                            if not self.__leftMenu.has_key(subfolder):
                                self.__leftMenu[subfolder] = []

                            # add this file if it does not exist
                            if self.__leftMenu[subfolder].count(
                                    classname) == 0:
                                self.__leftMenu[subfolder].append(classname)

                        # add the current symbol
                        classes[classname][identifier] = {
                            'public': privacy,
                            'type': type,
                            'doc': jsdocBuffer,
                            'params': params,
                            'returns': returns
                        }

                        self.__totalSymbols += 1

                        # clear the buffer and all other symbol specific data
                        jsdocBuffer = ''
                        type = -1
                        privacy = 0
                        returns = []
                        params = []
                        # clear the state switches
                        queryIdentifier = False

            # add to files
            # filename = os.path.basename( filename )
            self.__files[filename] = classes
            self.__exportations[classname] = exports

            #
            # mark all exported symbols automatically as public
            #
            for c in classes.keys():
                # check all detected classes
                self.__updatePrivacy(c)

        #
        # now all files have been parsed
        #

        # map symbols along the inheritance tree
        for i in self.__inheritances:
            self.inherit(i)
Esempio n. 2
0
    def run(self, options=None):
        '''
    Performs the action.
    '''

        print 'Generating dependency file for ' + config.SOFTWARE_SHORT + '...'

        # grab all js files
        filefinder = JSFileFinder()
        jsfiles = filefinder.run(['USE_INCLUDES'])

        arguments = []

        # closure base path
        basepath = os.path.dirname(
            os.path.dirname(config.CLOSUREDEPSWRITER_PATH))

        # set the output file
        arguments.extend(['--output_file=' + config.DEPS_OUTPUT_PATH])

        # add js files
        for j in jsfiles:
            arguments.extend([
                '--path_with_depspath=' + j + ' ' +
                os.path.relpath(j, basepath)
            ])

        #
        # call the closure depswriter
        #

        # make sure the depswriter is executable
        st = os.stat(config.CLOSUREDEPSWRITER_PATH)
        os.chmod(config.CLOSUREDEPSWRITER_PATH, st.st_mode | stat.S_IEXEC)

        command = [config.CLOSUREDEPSWRITER_PATH]
        command.extend(arguments)

        process = subprocess.Popen(command,
                                   bufsize=0,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT)

        # no output is good
        noOutput = True

        # print any output in red since it probably indicates an error
        for line in process.stdout:
            line = line.strip('\n')
            print Colors.RED + line + Colors._CLEAR
            noOutput = False

        if noOutput:

            # all good and done
            print Colors.ORANGE + 'Dependency file ' + Colors.PURPLE + config.DEPS_OUTPUT_PATH + Colors.ORANGE + ' generated. ' + Colors._CLEAR
            print Colors.ORANGE + 'Usage:' + Colors._CLEAR
            print Colors.CYAN + '  <script type="text/javascript" src="' + os.path.relpath(
                config.CLOSUREGOOGBASE_PATH,
                os.path.join(config.SOFTWARE_PATH,
                             '../')) + '"></script>' + Colors._CLEAR
            print Colors.CYAN + '  <script type="text/javascript" src="' + os.path.relpath(
                config.DEPS_OUTPUT_PATH,
                os.path.join(config.SOFTWARE_PATH,
                             '../')) + '"></script>' + Colors._CLEAR

        else:

            # maybe an error
            print Colors.ORANGE + 'Could not generate dependency file.' + Colors._CLEAR
Esempio n. 3
0
    def run(self, options=None):
        '''
    Performs the action.
    '''

        print 'Building ' + config.SOFTWARE_SHORT + '...'

        # grab all js files
        filefinder = JSFileFinder()
        jsfiles = filefinder.run()

        arguments = []

        # add js files
        for j in jsfiles:
            arguments.extend(['-i', j])

        # add the project root
        arguments.extend(['--root', config.SOFTWARE_PATH])

        # set the output mode to compiled
        arguments.extend(['-o', 'compiled'])

        # configure the compiler path
        arguments.extend(['-c', config.CLOSURECOMPILER_PATH])

        # configure the output file
        arguments.extend(['--output_file', config.BUILD_OUTPUT_PATH])

        # configure additional compiler arguments
        arguments.extend(['-f', '--warning_level=VERBOSE'])  # verbose
        arguments.extend(['-f', '--jscomp_warning=missingProperties'
                          ])  # enable strict mode 1
        arguments.extend(['-f', '--jscomp_warning=checkTypes'
                          ])  # enable strict mode 2
        arguments.extend(['-f',
                          '--summary_detail_level=3'])  # always show summary
        arguments.extend(['-f', '--define=goog.DEBUG=false'
                          ])  # turn of closure library debugging

        # add the goog/deps.js file from closure according to
        # https://code.google.com/p/closure-library/wiki/FrequentlyAskedQuestions#When_I_compile_with_type-checking_on,_I_get_warnings_about_unkno
        arguments.extend(['-f', '--js=' + config.CLOSURELIBRARY_DEPS_PATH])

        # if enabled, set debug options
        if options.debug:
            arguments.extend(['-f', '--debug'])
            arguments.extend(['-f', '--formatting=PRETTY_PRINT'])

        if options.simpleoptimizations:
            arguments.extend([
                '-f', '--compilation_level=SIMPLE_OPTIMIZATIONS'
            ])  # advanced compilation
        else:
            arguments.extend([
                '-f', '--compilation_level=ADVANCED_OPTIMIZATIONS'
            ])  # advanced compilation

        #
        # call the compiler (through the closure builder)
        #

        # make sure the closurebuilder is executable
        st = os.stat(config.CLOSUREBUILDER_PATH)
        os.chmod(config.CLOSUREBUILDER_PATH, st.st_mode | stat.S_IEXEC)

        command = ['python', config.CLOSUREBUILDER_PATH]
        command.extend(arguments)

        process = subprocess.Popen(command,
                                   bufsize=0,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT)

        # ignore the next X lines
        ignoreNext = 0

        # save warnings and errors in a log
        logActive = False
        log = []

        # fancy displaying using ANSI colors
        for line in process.stdout:

            if ignoreNext > 0:
                # we ignore this line
                ignoreNext -= 1
                continue

            line = line.strip('\n')
            color = Colors._CLEAR  # default is no color

            # colorize depending on line content
            if line.find('Scanning') != -1:
                color = Colors.YELLOW
            elif line.find('scanned') != -1:
                color = Colors.YELLOW
            elif line.find('Building') != -1:
                color = Colors.PURPLE
            elif line.find('Compiling') != -1:
                color = Colors.PURPLE
                # start logging now
                logActive = True
            elif line.find('ERROR') != -1:
                color = Colors.RED
            elif line.find('WARNING') != -1:
                # this is a warning, only display these if verbose mode is on
                if not options.verbose:
                    ignoreNext = 3  # and ignore the next 2 lines
                    continue

                color = Colors.ORANGE

            if logActive:
                # log this line if we are in logging mode
                log.append(line)

            # print colored line
            print color + line + Colors._CLEAR

        # we have errors and warnings logged now
        log = log[
            1:
            -1]  # remove first and last log entries since they are additional information

        # now we create a dashboard submission file
        cdasher = CDash()
        xmlfile = cdasher.run(['Build', log, True])

        with open(
                os.path.join(config.TEMP_PATH,
                             config.SOFTWARE_SHORT + '_Build.xml'), 'w') as f:
            f.write(xmlfile)

        # and add a timestamp to the compiled file
        with open(config.BUILD_OUTPUT_PATH, 'r') as f:

            content = f.read()  # read everything in the file
            now = datetime.datetime.now()
            content_with_timestamp = content.replace(
                '###TIMESTAMP###', now.strftime('%Y-%m-%d %H:%M:%S'))

        with open(config.BUILD_OUTPUT_PATH, 'w') as f:

            f.write(content_with_timestamp)  # write the new stuff

        # and attach the license
        licenser = Licenser()
        licenser.run()

        print Colors.ORANGE + 'Compiled file ' + Colors.CYAN + config.BUILD_OUTPUT_PATH + Colors.ORANGE + ' written. ' + Colors._CLEAR
Esempio n. 4
0
  def run( self, options=None ):
    '''
    Performs the action.
    '''

    print 'Building ' + config.SOFTWARE_SHORT + '...'

    # grab all js files
    filefinder = JSFileFinder()
    jsfiles = filefinder.run()

    arguments = []

    # add js files
    for j in jsfiles:
      arguments.extend( ['-i', j] )

    # add the project root
    arguments.extend( ['--root', config.SOFTWARE_PATH] )

    # set the output mode to compiled
    arguments.extend( ['-o', 'compiled'] )

    # configure the compiler path
    arguments.extend( ['-c', config.CLOSURECOMPILER_PATH] )

    # configure the output file
    arguments.extend( ['--output_file', config.BUILD_OUTPUT_PATH] )

    # configure additional compiler arguments
    arguments.extend( [ '-f', '--warning_level=VERBOSE'] ) # verbose
    arguments.extend( [ '-f', '--compilation_level=ADVANCED_OPTIMIZATIONS'] ) # advanced compilation
    arguments.extend( [ '-f', '--jscomp_warning=missingProperties'] ) # enable strict mode 1
    arguments.extend( [ '-f', '--jscomp_warning=checkTypes'] ) # enable strict mode 2
    arguments.extend( ['-f', '--summary_detail_level=3'] ) # always show summary
    arguments.extend( [ '-f', '--define=goog.DEBUG=false'] ) # turn of closure library debugging

    # if enabled, set debug options
    if options.debug:
      arguments.extend( ['-f', '--debug'] )
      arguments.extend( ['-f', '--formatting=PRETTY_PRINT'] )


    #
    # call the compiler (through the closure builder)
    #
    command = [config.CLOSUREBUILDER_PATH]
    command.extend( arguments )

    process = subprocess.Popen( command, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )

    # ignore the next X lines
    ignoreNext = 0

    # save warnings and errors in a log
    logActive = False
    log = []

    # fancy displaying using ANSI colors
    for line in process.stdout:

      if ignoreNext > 0:
        # we ignore this line
        ignoreNext -= 1
        continue

      line = line.strip( '\n' )
      color = Colors._CLEAR # default is no color

      # colorize depending on line content
      if line.find( 'Scanning' ) != -1:
        color = Colors.YELLOW
      elif line.find( 'scanned' ) != -1:
        color = Colors.YELLOW
      elif line.find( 'Building' ) != -1:
        color = Colors.PURPLE
      elif line.find( 'Compiling' ) != -1:
        color = Colors.PURPLE
        # start logging now
        logActive = True
      elif line.find( 'ERROR' ) != -1:
        color = Colors.RED
      elif line.find( 'WARNING' ) != -1:
        # this is a warning, only display these if verbose mode is on
        if not options.verbose:
          ignoreNext = 3 # and ignore the next 2 lines
          continue

        color = Colors.ORANGE

      if logActive:
        # log this line if we are in logging mode
        log.append( line )

      # print colored line
      print color + line + Colors._CLEAR

    # we have errors and warnings logged now
    log = log[1:-1] # remove first and last log entries since they are additional information

    # now we create a dashboard submission file
    cdasher = CDash()
    xmlfile = cdasher.run( ['Build', log] )

    with open( os.path.join( config.TEMP_PATH, config.SOFTWARE_SHORT + '_Build.xml' ), 'w' ) as f:
      f.write( xmlfile )

    # and attach the license
    licenser = Licenser()
    licenser.run()

    print Colors.ORANGE + 'Compiled file ' + Colors.CYAN + config.BUILD_OUTPUT_PATH + Colors.ORANGE + ' written. ' + Colors._CLEAR