Exemple #1
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
Exemple #2
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

        # 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"])

        #
        # 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
Exemple #3
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)
Exemple #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', '--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
Exemple #5
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
Exemple #6
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, 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
Exemple #7
0
  def findSymbols( self ):
    '''
    Find and lookup symbols including inheritance relations.
    '''

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

    # .. 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
      classname = ''
      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

                # we have the current filename here as j
                subfolder = os.path.dirname( filename ).split( os.sep )[-1]

                # ignore toplevel files
                if not subfolder == '..':

                  # 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 )

                # 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] = {}

            # 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 )
Exemple #8
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