def runLint(jobconf, classes): def getFilteredClassList(classes, includePatt_, excludePatt_): # Although lint-check doesn't work with dependencies, we allow # '=' in class pattern for convenience; stripp those now intelli, explicit = textutil.splitPrefixedStrings(includePatt_) includePatt = intelli + explicit intelli, explicit = textutil.splitPrefixedStrings(excludePatt_) excludePatt = intelli + explicit if len(includePatt): incRegex = map(textutil.toRegExpS, includePatt) incRegex = re.compile("|".join(incRegex)) else: incRegex = re.compile(".") # catch-all if len(excludePatt): excRegex = map(textutil.toRegExpS, excludePatt) excRegex = re.compile("|".join(excRegex)) else: excRegex = re.compile("^$") # catch-none classesFiltered = (c for c in classes if incRegex.search(c) and not excRegex.search(c)) return classesFiltered # ---------------------------------------------------------------------- if not jobconf.get('lint-check', False) or not jobconf.get( 'lint-check/run', False): return console = Context.console lib_class_names = classes.keys() console.info("Checking Javascript source code...") console.indent() # Options lintJob = jobconf opts = lint.defaultOptions() opts.include_patts = lintJob.get('include', []) # this is for future use opts.exclude_patts = lintJob.get('exclude', []) classesToCheck = list( getFilteredClassList(lib_class_names, opts.include_patts, opts.exclude_patts)) opts.library_classes = lib_class_names opts.class_namespaces = [ x[:x.rfind(".")] for x in opts.library_classes if x.find(".") > -1 ] # the next requires that the config keys and option attributes be identical (modulo "-"_") for option, value in lintJob.get("lint-check").items(): setattr(opts, option.replace("-", "_"), value) for pos, classId in enumerate(classesToCheck): console.debug("Checking %s" % classId) tree = classes[classId].tree() lint.lint_check(tree, classId, opts) console.outdent()
def runLint(jobconf, classes): def getFilteredClassList(classes, includePatt_, excludePatt_): # Although lint-check doesn't work with dependencies, we allow # '=' in class pattern for convenience; stripp those now intelli, explicit = textutil.splitPrefixedStrings(includePatt_) includePatt = intelli + explicit intelli, explicit = textutil.splitPrefixedStrings(excludePatt_) excludePatt = intelli + explicit if len(includePatt): incRegex = map(textutil.toRegExpS, includePatt) incRegex = re.compile("|".join(incRegex)) else: incRegex = re.compile(".") # catch-all if len(excludePatt): excRegex = map(textutil.toRegExpS, excludePatt) excRegex = re.compile("|".join(excRegex)) else: excRegex = re.compile("^$") # catch-none classesFiltered = (c for c in classes if incRegex.search(c) and not excRegex.search(c)) return classesFiltered # ---------------------------------------------------------------------- if not jobconf.get('lint-check', False) or not jobconf.get('lint-check/run', False): return console = Context.console lib_class_names = classes.keys() console.info("Checking Javascript source code...") console.indent() # Options lintJob = jobconf opts = lint.defaultOptions() opts.include_patts = lintJob.get('include', []) # this is for future use opts.exclude_patts = lintJob.get('exclude', []) classesToCheck = list(getFilteredClassList(lib_class_names, opts.include_patts, opts.exclude_patts)) opts.library_classes = lib_class_names opts.class_namespaces = [x[:x.rfind(".")] for x in opts.library_classes if x.find(".")>-1] # the next requires that the config keys and option attributes be identical (modulo "-"_") for option, value in lintJob.get("lint-check").items(): setattr(opts, option.replace("-","_"), value) for pos, classId in enumerate(classesToCheck): console.debug("Checking %s" % classId) tree = classes[classId].tree() lint.lint_check(tree, classId, opts) console.outdent()
def lint_warnings(self, lint_opts): classInfo, mTime = self._getClassCache() if (not 'lint-basics' in classInfo and True): # not up-to-date?! when is the class cache invalidated?! warns = lint.lint_check(self.tree(), self.id, lint_opts) classInfo['lint-basics'] = (warns, time.time()) self._writeClassCache(classInfo) return classInfo['lint-basics'][0]
def do_lint(file_, popup): if popup: logger = util.PopupLogger() else: logger = util.TextMateLogger() logger.printHeader("qooxdoo JavaScript lint", "qooxdoo JavaScript lint") try: opts = lint.defaultOptions() opts.allowed_globals = ['qx', 'qxWeb', 'q'] tree_ = treegenerator.createFileTree_from_string( codecs.open(file_, "r", "utf-8").read()) tree_ = scopes.create_scopes(tree_) if not getattr(context, 'console', None): context.console = Log() if not getattr(context, 'jobconf', None): context.jobconf = ExtMap() context.jobconf.set("lint-check/warn-unknown-jsdoc-keys", True) lint.lint_check(tree_, "", opts) except treegenerator.SyntaxException, e: logger.log(file_, 0, 0, str(e))
def main(argv=None): # init Context module Context.console = Log() Context.jobconf = {} if argv is None: argv = sys.argv parser = OptionParser( description="Checks ECMAScript/JavaScript files for common errors.") parser.add_option( "--action", "-a", dest="actions", metavar="ACTION", choices=[ "ALL", "undefined_variables", "unused_variables", "multidefined_variables", "maps", "blocks", "fields" ], action="append", default=[], help= """Performs the given checks on the input files. This parameter may be supplied multiple times. Valid arguments are: "ALL" (default): Perform all checks "undefined_variables": Look for identifier, which are referenced in the global scope. This action can find misspelled identifier and missing 'var' statements. You can use the '-g' flag to add valid global identifiers. "unused_variables": Look for identifier, which are defined but never used. "multidefined_variables": Look for identifier, which are defined multiple times. "blocks" : Look for single statments in bodies of if's and loops that are not enclosed by braces. "fields" : Look for class attributes, checking definedness, privates and protected fields. "maps": Look for duplicate keys in map declarations. """) parser.add_option("-g", dest="globals", help="Add an allowed global identifier GLOBAL", metavar="GLOBAL", action="append", default=[]) (options, args) = parser.parse_args(argv) if len(args) == 1: parser.print_help() sys.exit(1) if options.globals: globals_ = options.globals else: globals_ = [] checkAll = "ALL" in options.actions or len(options.actions) == 0 # construct opts argument for lint_check keys_map ={ # map cli 'action' keys to lint.options "undefined_variables" : ["ignore_undefined_globals"], "unused_variables" : ["ignore_unused_variables", "ignore_unused_parameter"], "multidefined_variables" : ["ignore_multiple_vardecls"], "maps" : ["ignore_multiple_mapkeys"], "blocks" : ["ignore_no_loop_block"], "fields" : ["ignore_reference_fields", "ignore_undeclared_privates"], } opts = lint.defaultOptions() opts.allowed_globals = options.globals for opt in (o for o in vars(opts) if o.startswith("ignore_")): if checkAll: setattr(opts, opt, False) else: for argopt in keys_map: if argopt in options.actions and opt in keys_map[argopt]: setattr(opts, opt, False) break else: setattr(opts, opt, True) for filename in args[1:]: tree_ = treegenerator.createFileTree_from_string( codecs.open(filename, "r", "utf-8").read()) tree_ = scopes.create_scopes(tree_) lint.lint_check(tree_, filename, opts) return ## TODO: rc
def lint_check(classObj, opts): tree = classObj.tree() return lint.lint_check(tree, classObj.id, opts)
# annotate scopes reg. load time evaluation if True: if hasattr(tree,'scope') and tree.scope: console.outdent() console.debug("Annotating scopes with load time information: %s..." % self.id) console.indent() load_time.load_time_check(tree.scope) # lint check if False: # currently done in MClassDependencies, due to global classList console.outdent() console.debug("Checking JavaScript source code: %s..." % self.id) console.indent() # construct parse-level check options opts = lint.defaultOptions() lint.lint_check(tree, self.id, opts) # store unoptimized tree cache.write(cacheId, tree, memory=tradeSpaceForSpeed) console.outdent() return tree ## # Raises in case of inconsistencies, otherwise returns None # def checkClassId(self, tree): className = None # not-found return value filePathId = self.id qxDefine = treeutil.findQxDefine(tree)
console.outdent() console.debug( "Annotating scopes with load time information: %s..." % self.id) console.indent() load_time.load_time_check(tree.scope) # lint check if False: # currently done in MClassDependencies, due to global classList console.outdent() console.debug("Checking JavaScript source code: %s..." % self.id) console.indent() # construct parse-level check options opts = lint.defaultOptions() lint.lint_check(tree, self.id, opts) # store unoptimized tree cache.write(cacheId, tree, memory=tradeSpaceForSpeed) console.outdent() return tree ## # Raises in case of inconsistencies, otherwise returns None # def checkClassId(self, tree): className = None # not-found return value filePathId = self.id qxDefine = treeutil.findQxDefine(tree) if qxDefine:
def buildShallowDeps(tree=None): load = [] run = [] ignore = [ DependencyItem(x, '', "|DefaultIgnoredNamesDynamic|") for x in self.defaultIgnoredNamesDynamic ] console.debug("Analyzing tree: %s" % self.id) console.indent() # Read meta data meta = self.getHints() metaLoad = meta.get("loadtimeDeps", []) metaRun = meta.get("runtimeDeps", []) metaOptional = meta.get("optionalDeps", []) metaIgnore = meta.get("ignoreDeps", []) metaIgnore.extend(metaOptional) # regexify globs in metaignore metaIgnore = map(MetaIgnore, metaIgnore) # Turn strings into DependencyItems() for target, metaHint in ((load, metaLoad), (run, metaRun), (ignore, metaIgnore)): for key in metaHint: # add all feature checks if requested if key == "feature-checks" and metaHint in (metaLoad, metaRun): target.extend( self.getAllEnvChecks(-1, metaHint == metaLoad)) # turn an entry into a DependencyItem elif isinstance(key, types.StringTypes): sig = key.split('#', 1) className = sig[0] attrName = sig[1] if len(sig) > 1 else '' target.append( DependencyItem(className, attrName, self.id, "|hints|")) # Read source tree data if not tree: if variantSet: # a filled variantSet map means that "variants" optimization is wanted tree = self.optimize(None, ["variants"], variantSet) else: tree = self.tree() # do lint checking here, as we have a classList ("ClassesAll") to check globals against if True: # construct parse-level lint options opts = lint.defaultOptions() opts.library_classes = ClassesAll.keys() opts.class_namespaces = ClassList.namespaces_from_classnames( opts.library_classes) # some sensible settings (deviating from defaultOptions) opts.ignore_no_loop_block = True opts.ignore_reference_fields = True opts.ignore_undeclared_privates = True opts.ignore_unused_variables = True # override from config jobConf = Context.jobconf for option, value in jobConf.get("lint-check", {}).items(): setattr(opts, option.replace("-", "_"), value) lint.lint_check(tree, self.id, opts) # analyze tree treeDeps = [] # will be filled by _analyzeClassDepsNode self._analyzeClassDepsNode(tree, treeDeps, inLoadContext=True) # Process source tree data for dep in treeDeps: if dep.isLoadDep: if "auto-require" not in metaIgnore: item = dep.name if item in metaIgnore: pass elif item in metaLoad: console.warn("%s: #require(%s) is auto-detected" % (self.id, item)) else: # adding all items to list (the second might have needsRecursion) load.append(dep) else: # runDep if "auto-use" not in metaIgnore: item = dep.name if item in metaIgnore: pass #elif item in (x.name for x in load): # pass elif item in metaRun: console.warn("%s: #use(%s) is auto-detected" % (self.id, item)) else: # adding all items to list (to comply with the 'load' deps) run.append(dep) console.outdent() # Build data structure deps = { "load": load, "run": run, "ignore": ignore, } return deps
def buildShallowDeps(tree=None): load = [] run = [] ignore = [DependencyItem(x, '', "|DefaultIgnoredNamesDynamic|") for x in self.defaultIgnoredNamesDynamic] console.debug("Analyzing tree: %s" % self.id) console.indent() # Read meta data meta = self.getHints() metaLoad = meta.get("loadtimeDeps", []) metaRun = meta.get("runtimeDeps" , []) metaOptional = meta.get("optionalDeps", []) metaIgnore = meta.get("ignoreDeps" , []) metaIgnore.extend(metaOptional) # regexify globs in metaignore metaIgnore = map(MetaIgnore, metaIgnore) # Turn strings into DependencyItems() for target,metaHint in ((load,metaLoad), (run,metaRun), (ignore,metaIgnore)): for key in metaHint: # add all feature checks if requested if key == "feature-checks" and metaHint in (metaLoad, metaRun): target.extend(self.getAllEnvChecks(-1, metaHint==metaLoad)) # turn an entry into a DependencyItem elif isinstance(key, types.StringTypes): sig = key.split('#',1) className = sig[0] attrName = sig[1] if len(sig)>1 else '' target.append(DependencyItem(className, attrName, self.id, "|hints|")) # Read source tree data if not tree: if variantSet: # a filled variantSet map means that "variants" optimization is wanted tree = self.optimize(None, ["variants"], variantSet) else: tree = self.tree() # do lint checking here, as we have a classList ("ClassesAll") to check globals against if True: # construct parse-level lint options opts = lint.defaultOptions() opts.library_classes = ClassesAll.keys() opts.class_namespaces = ClassList.namespaces_from_classnames(opts.library_classes) # some sensible settings (deviating from defaultOptions) opts.ignore_no_loop_block = True opts.ignore_reference_fields = True opts.ignore_undeclared_privates = True opts.ignore_unused_variables = True # override from config jobConf = Context.jobconf for option, value in jobConf.get("lint-check", {}).items(): setattr(opts, option.replace("-","_"), value) lint.lint_check(tree, self.id, opts) # analyze tree treeDeps = [] # will be filled by _analyzeClassDepsNode self._analyzeClassDepsNode(tree, treeDeps, inLoadContext=True) # Process source tree data for dep in treeDeps: if dep.isLoadDep: if "auto-require" not in metaIgnore: item = dep.name if item in metaIgnore: pass elif item in metaLoad: console.warn("%s: #require(%s) is auto-detected" % (self.id, item)) else: # adding all items to list (the second might have needsRecursion) load.append(dep) else: # runDep if "auto-use" not in metaIgnore: item = dep.name if item in metaIgnore: pass #elif item in (x.name for x in load): # pass elif item in metaRun: console.warn("%s: #use(%s) is auto-detected" % (self.id, item)) else: # adding all items to list (to comply with the 'load' deps) run.append(dep) console.outdent() # Build data structure deps = { "load" : load, "run" : run, "ignore" : ignore, } return deps
def main(argv=None): # init Context module Context.console = Log() Context.jobconf = {} if argv is None: argv = sys.argv parser = OptionParser(description="Checks ECMAScript/JavaScript files for common errors.") parser.add_option( "--action", "-a", dest="actions", metavar="ACTION", choices=["ALL", "undefined_variables", "unused_variables", "multidefined_variables", "maps", "blocks", "fields"], action="append", default=[], help="""Performs the given checks on the input files. This parameter may be supplied multiple times. Valid arguments are: "ALL" (default): Perform all checks "undefined_variables": Look for identifier, which are referenced in the global scope. This action can find misspelled identifier and missing 'var' statements. You can use the '-g' flag to add valid global identifiers. "unused_variables": Look for identifier, which are defined but never used. "multidefined_variables": Look for identifier, which are defined multiple times. "blocks" : Look for single statments in bodies of if's and loops that are not enclosed by braces. "fields" : Look for class attributes, checking definedness, privates and protected fields. "maps": Look for duplicate keys in map declarations. """ ) parser.add_option( "-g", dest="globals", help="Add an allowed global identifier GLOBAL", metavar="GLOBAL", action="append", default=[] ) (options, args) = parser.parse_args(argv) if len(args) == 1: parser.print_help() sys.exit(1) if options.globals: globals_ = options.globals else: globals_ = [] checkAll = "ALL" in options.actions or len(options.actions) == 0 # construct opts argument for lint_check keys_map ={ # map cli 'action' keys to lint.options "undefined_variables" : ["ignore_undefined_globals"], "unused_variables" : ["ignore_unused_variables", "ignore_unused_parameter"], "multidefined_variables" : ["ignore_multiple_vardecls"], "maps" : ["ignore_multiple_mapkeys"], "blocks" : ["ignore_no_loop_block"], "fields" : ["ignore_reference_fields", "ignore_undeclared_privates"], } opts = lint.defaultOptions() opts.allowed_globals = options.globals for opt in (o for o in vars(opts) if o.startswith("ignore_")): if checkAll: setattr(opts, opt, False) else: for argopt in keys_map: if argopt in options.actions and opt in keys_map[argopt]: setattr(opts, opt, False) break else: setattr(opts, opt, True) for filename in args[1:]: tree_ = treegenerator.createFileTree_from_string(codecs.open(filename, "r", "utf-8").read()) tree_ = scopes.create_scopes(tree_) lint.lint_check(tree_, filename, opts) return ## TODO: rc
class MClassCode(object): # -------------------------------------------------------------------------- # Tree Interface # -------------------------------------------------------------------------- ## # Interface method. Delivers class syntax tree: # - handles cache # - can be called with alternative parser (treegenerator) # def tree(self, treegen=treegenerator, force=False): cache = self.context['cache'] console = self.context['console'] tradeSpaceForSpeed = False # Caution: setting this to True seems to make builds slower, at least on some platforms!? cacheId = "tree%s-%s-%s" % (treegen.tag, self.path, util.toString({})) self.treeId = cacheId # Lookup for unoptimized tree tree, _ = cache.read(cacheId, self.path, memory=tradeSpaceForSpeed) # Tree still undefined?, create it! if tree == None or force: console.debug("Parsing file: %s..." % self.id) console.indent() # tokenize fileContent = filetool.read(self.path, self.encoding) fileId = self.path if self.path else self.id try: tokens = tokenizer.parseStream(fileContent, self.id) except SyntaxException, e: # add file info e.args = (e.args[0] + "\nFile: %s" % fileId,) + e.args[1:] raise e # parse console.outdent() console.debug("Generating tree: %s..." % self.id) console.indent() try: tree = treegen.createFileTree(tokens, fileId) except SyntaxException, e: # add file info e.args = (e.args[0] + "\nFile: %s" % fileId,) + e.args[1:] raise e # annotate with scopes if True: console.outdent() console.debug("Calculating scopes: %s..." % self.id) console.indent() tree = scopes.create_scopes(tree) #if self.id == "gui.Application": # import pydb; pydb.debugger() #tree.scope.prrnt() # lint check if False: console.outdent() console.debug("Checking JavaScript source code: %s..." % self.id) console.indent() # construct parse-level check options opts = lint.defaultOptions() lint.lint_check(tree, self.id, opts) # store unoptimized tree cache.write(cacheId, tree, memory=tradeSpaceForSpeed) console.outdent()