コード例 #1
0
ファイル: qxCoreEnv.js プロジェクト: eric-christian/qooxdoo
/**
 * Extracts values from <code>qx.Bootstrap.define().statics._checksMap</code>.
 *
 * @param {string} classCode - js code of Environment class.
 * @returns {Object} envKeys and envMethodNames
 */
function getFeatureTable(classCode) {

  function isFeatureMap (node) {
    return (node.type === 'Property'
      && node.key.type === 'Identifier'
      && node.key.name === '_checksMap'
      && node.value.type ===  'ObjectExpression'
    );
  }

  var featureMap = {};
  // parse classCode
  var tree = esprima.parse(classCode);

  // search feature map
  var controller = new estraverse.Controller();
  controller.traverse(tree, {
    enter : function (node, parent) {
      if (isFeatureMap(node)) {
        featureMap = node.value;
      }
    }
  });
  return eval('(' + escodegen.generate(featureMap) + ')');
}
コード例 #2
0
ファイル: qxCoreEnv.js プロジェクト: Theosis/qooxdoo
/**
 * extract values from qx.Bootstrap.define().statics._checksMap
 */
function getFeatureTable(classCode) {

    function is_feature_map (node) {
        return (node.type === "Property"
            && node.key.type === "Identifier"
            && node.key.name === "_checksMap"
            && node.value.type ===  "ObjectExpression"
            /*
            && node.parent
            && node.parent.type == "Property"
            && node.parent.key.type == "Identifier"
            && node.parent.key.name == "statics"
            */
        );
    }

    var feature_map = {};
    // parse classCode
    var etree = esprima.parse(classCode);
    //parentAnnotator.annotate(etree);

    // search feature map
    var controller = new estraverse.Controller();
    controller.traverse(etree, {
        enter : function (node, parent) {
            if (is_feature_map(node)) {
                feature_map = node.value;
            }
        }
    });
    return eval('(' + escodegen.generate(feature_map) + ')');
}
コード例 #3
0
ファイル: qxCoreEnv.js プロジェクト: eric-christian/qooxdoo
/**
 * Finds variant nodes (<code>qx.core.Environment.(select(Async)?|get(Async)?|filter)</code> calls)
 * within an esprima AST.
 *
 * @param {Object} tree - esprima AST
 * @returns {Object[]} node - esprima node
 * @see {@link http://esprima.org/doc/#ast|esprima AST}
 */
function findVariantNodes(tree) {
  var result = [];
  var interestingEnvMethods = {
    'select'      : true,
    'selectAsync' : true,
    'get'         : true,
    'getAsync'    : true,
    'filter'      : true
  };

  // walk tree
  var controller = new estraverse.Controller();
  controller.traverse(tree, {
    enter : function (node, parent) {
      // pick calls to qx.core.Environment.get|select|filter
      if (node.type === 'CallExpression'
          && util.get(node, 'callee.object.object.object.name') === 'qx'
          && util.get(node, 'callee.object.object.property.name') === 'core'
          && util.get(node, 'callee.object.property.name') === 'Environment'
          && util.get(node, 'callee.property.name') in interestingEnvMethods) {
            result.push(node);
      }
    }
  });
  return result;
}
コード例 #4
0
ファイル: qxCoreEnv.js プロジェクト: halcwb/qooxdoo
/**
 * Extracts env keys (first argument) from
 * <code>qx.core.Environment.add('engine.name', function(){ ... })</code> calls and
 * stores them with their providing class (e.g. {'engine.name': 'qx.bom.client.Engine', 'engine.version': ...}).
 *
 * @param {Object} classCodeMap - js code of environment key provider classes e.g. {'qx.bom.client.Engine': 'long js code string'}
 * @returns {Object} envKeys and envProviderClasses.
 */
function getFeatureTable(classCodeMap) {

  function isQxCoreEnvAddCall (node) {
    return (node.type === 'CallExpression'
            && util.get(node, 'callee.object.object.object.name') === 'qx'
            && util.get(node, 'callee.object.object.property.name') === 'core'
            && util.get(node, 'callee.object.property.name') === 'Environment'
            && util.get(node, 'callee.property.name') === 'add');
  }

  var featureMap = {};
  for (var className in classCodeMap) {
    var tree = esprima.parse(classCodeMap[className]);

    var controller = new estraverse.Controller();
    controller.traverse(tree, {
      enter : function (node, parent) {
        if (isQxCoreEnvAddCall(node)) {
          featureMap[getKeyFromEnvCall(node)] = className;
        }
      }
    });
  }

  return featureMap;
}
コード例 #5
0
ファイル: qxCoreEnv.js プロジェクト: halcwb/qooxdoo
/**
 * Finds variant nodes (<code>qx.core.Environment.(select(Async)?|get(Async)?|filter)</code> calls)
 * within an esprima AST.
 *
 * @param {Object} tree - esprima AST
 * @returns {Object[]} node - esprima node
 * @see {@link http://esprima.org/doc/#ast|esprima AST}
 */
function findVariantNodes(tree) {
  var result = [];

  var controller = new estraverse.Controller();
  controller.traverse(tree, {
    enter : function (node, parent) {
      if (isQxCoreEnvironmentCall(node)) {
        result.push(node);
      }
    }
  });
  return result;
}
コード例 #6
0
ファイル: parameters.js プロジェクト: Supporting/shade.js
 enter: function (node) {
     var type = node.type,
         context, retVal = null;
     switch (type) {
         case Syntax.FunctionDeclaration:
             var parentContext = contextStack[contextStack.length - 1];
             parentContext.declareVariable(node.id.name, false);
             context = new Scope(node, parentContext, {name: node.id.name });
             contextStack.push(context);
             if (context.str() == functionName) {
                 if (environmentObjectPosition != -1 && node.params.length > environmentObjectPosition) {
                     activeParam = node.params[environmentObjectPosition].name;
                 }
             } else {
                 controller.skip();
             }
             break;
         case Syntax.CallExpression:
             var pos = node.arguments.reduce(function (prev, curr, index) {
                 if (curr.name && curr.name == activeParam)
                     return index;
                 return prev;
             }, -1);
             context = contextStack[contextStack.length - 1];
             var id = context.getVariableIdentifier(node.callee.name);
             if (id && !analyzedCalls[id]) {
                 analyzedCalls[id] = true;
                 merge(result, findParametersInFunction(id, program, pos, analyzedCalls));
             }
             break;
         default:
     }
 },
コード例 #7
0
ファイル: qxCoreEnv.js プロジェクト: Theosis/qooxdoo
function findVariantNodes(etree) {
    var result = [];
    // walk etree
    var controller = new estraverse.Controller();
    controller.traverse(etree, {
        enter : function (node, parent) {
            // pick calls to qx.core.Environment.get|select|filter
            if (node.type === 'CallExpression'
                && get(node, "callee.object.object.object.name") === 'qx'
                && get(node, "callee.object.object.property.name") === 'core'
                && get(node, "callee.object.property.name") === 'Environment'
                && get(node, "callee.property.name") in InterestingEnvMethods) {
                result.push(node);
            }
        }
    });
    return result;
}
コード例 #8
0
ファイル: qxCoreEnv.js プロジェクト: halcwb/qooxdoo
/**
 * Replaces select env calls with the computed value.
 *
 * @param {Object} tree - esprima AST
 * @param {Object} envMap - environment settings
 * @returns {Object} resultTree - manipulated (desctructive) esprima AST
 * @see {@link http://esprima.org/doc/#ast|esprima AST}
 */
function replaceEnvCallSelect(tree, envMap) {
  var controller = new estraverse.Controller();
  var resultTree = controller.replace(tree, {
    enter : function (node, parent) {
      if (isQxCoreEnvironmentCall(node, ["select"])) {
        var envKey = getKeyFromEnvCall(node);
        try {
          return getEnvSelectValueByKey(node, envMap[envKey]);
        } catch (error) {
          // intentionally empty
          // => no return means no replacement
          // possible reasons:
          //   * envMap has no envKey because the envKey is runtime based (os.version)
          //     and cannot be configured upfront.
        }
      }
    }
  });

  return resultTree;
}
コード例 #9
0
ファイル: qxCoreEnv.js プロジェクト: halcwb/qooxdoo
/**
 * Replaces get env calls with the computed value.
 *
 * @param {Object} tree - esprima AST
 * @param {Object} envMap - environment settings
 * @returns {Object} resultTree - manipulated (desctructive) esprima AST
 * @see {@link http://esprima.org/doc/#ast|esprima AST}
 */
function replaceEnvCallGet(tree, envMap) {
  var controller = new estraverse.Controller();
  var resultTree = controller.replace(tree, {
    enter : function (node, parent) {
      if (isQxCoreEnvironmentCall(node, ["get"])) {
        var envKey = getKeyFromEnvCall(node);
        if (envMap && envKey in envMap) {
          return {
            "type": "Literal",
            "value": envMap[envKey],
            "raw": ((typeof(envMap[envKey]) === "string")
                   ? "\""+envMap[envKey]+"\""
                   : envMap[envKey].toString())
          };
        }
      }
    }
  });

  return resultTree;
}
コード例 #10
0
ファイル: qxCoreEnv.js プロジェクト: halcwb/qooxdoo
/**
 * Extracts values from <code>qx.Bootstrap.define().statics._defaults</code>.
 *
 * @param {string} classCode - js code of Environment class.
 * @returns {Object} envKeys and envValues.
 */
function extractEnvDefaults(classCode) {
  function isDefaultsMap (node) {
    return (node.type === 'Property'
      && node.key.type === 'Identifier'
      && node.key.name === '_defaults'
      && node.value.type === 'ObjectExpression'
    );
  }

  var defaultsMap = {};
  var tree = esprima.parse(classCode);

  var controller = new estraverse.Controller();
  controller.traverse(tree, {
    enter : function (node, parent) {
      if (isDefaultsMap(node)) {
        defaultsMap = node.value;
      }
    }
  });

  return eval('(' + escodegen.generate(defaultsMap) + ')');
}
コード例 #11
0
ファイル: parameters.js プロジェクト: Supporting/shade.js
    var findParametersInFunction = function (functionName, program, environmentObjectPosition, analyzedCalls) {
        var context = new Scope(program, null, {name: "global"});
        var contextStack = [context];

        var result = { shaderParameters: [], systemParameters: [] };
        analyzedCalls = analyzedCalls || {};
        // console.log("Looking for: ", functionName, environmentObjectPosition);

        var activeParam = null;

        var controller = new walk.Controller();
        controller.traverse(program, {
            enter: function (node) {
                var type = node.type,
                    context, retVal = null;
                switch (type) {
                    case Syntax.FunctionDeclaration:
                        var parentContext = contextStack[contextStack.length - 1];
                        parentContext.declareVariable(node.id.name, false);
                        context = new Scope(node, parentContext, {name: node.id.name });
                        contextStack.push(context);
                        if (context.str() == functionName) {
                            if (environmentObjectPosition != -1 && node.params.length > environmentObjectPosition) {
                                activeParam = node.params[environmentObjectPosition].name;
                            }
                        } else {
                            controller.skip();
                        }
                        break;
                    case Syntax.CallExpression:
                        var pos = node.arguments.reduce(function (prev, curr, index) {
                            if (curr.name && curr.name == activeParam)
                                return index;
                            return prev;
                        }, -1);
                        context = contextStack[contextStack.length - 1];
                        var id = context.getVariableIdentifier(node.callee.name);
                        if (id && !analyzedCalls[id]) {
                            analyzedCalls[id] = true;
                            merge(result, findParametersInFunction(id, program, pos, analyzedCalls));
                        }
                        break;
                    default:
                }
            },
            leave: function (node) {
                var type = node.type;
                switch (type) {
                    case Syntax.FunctionDeclaration:
                        contextStack.pop();
                        activeParam = null;
                        break;
                    case Syntax.MemberExpression:
                        var parameterName = node.property.name;
                        // In a specific parameter of the current method
                        if (activeParam && node.object.name == activeParam) {
                            addSystemParameter(parameterName, result.shaderParameters);
                        } // In 'this' is a system parameter
                        else if (node.object.type == Syntax.ThisExpression) {
                            addSystemParameter(parameterName, result.systemParameters, derivedSystemParameters);
                        } // In global variable '_env'
                        else if (node.object.name == "_env") {
                            addSystemParameter(parameterName, result.shaderParameters);
                        }
                        break;
                }
            }
        });

        return result;
    };
コード例 #12
0
    api.verify = function(text, config, filename, saveState) {

        var ast;

        // set the current parsed filename
        currentFilename = filename;

        if (!saveState) {
            this.reset();
        }

        ast = parse(text.replace(/^(#![^\r\n]+[\r\n]+)/, "//$1"));

        //if Esprima failed to parse the file, there's no sense in setting up rules
        if (ast) {
            // process initial config to make it safe to extend
            config = prepareConfig(config);

            // parse global comments and modify config
            config = modifyConfigFromComments(ast, config);

            // enable appropriate rules
            Object.keys(config.rules).filter(function(key) {
                if (typeof config.rules[key] === "number") {
                    return config.rules[key] > 0;
                } else if (Array.isArray(config.rules[key])) {
                    // Here the rule looks like [1, ...] - the first value is the key we want
                    return config.rules[key][0] > 0;
                } else {
                    return false;
                }
            }).forEach(function(key) {
                var ruleCreator = rules.get(key),
                    options = [],
                    rule;

                if (Array.isArray(config.rules[key])) {

                    // The additional config data is after the bool value
                    options = config.rules[key].slice(1);
                }

                if (ruleCreator) {
                    try {
                        rule = ruleCreator(new RuleContext(key, api, options));

                        // add all the node types as listeners
                        Object.keys(rule).forEach(function(nodeType) {
                            api.on(nodeType, rule[nodeType]);
                        });
                    } catch(ex) {
                        ex.message = "Error while loading rule '" + key + "': " + ex.message;
                        throw ex;
                    }

                } else {
                    throw new Error("Definition for rule '" + key + "' was not found.");
                }
            });

            // save config so rules can access as necessary
            currentConfig = config;
            currentText = text;
            controller = new estraverse.Controller();

            // gather data that may be needed by the rules
            currentScopes = escope.analyze(ast, { ignoreEval: true }).scopes;

            /* get all tokens from the ast and store them as a hashtable to
             * improve traversal speed when wanting to find tokens for a given
             * node
             */
            currentTokens = [];
            ast.tokens.forEach(function(token) {
                currentTokens[token.range[0]] = token;
            });

            // augment global scope with declared global variables
            addDeclaredGlobals(ast, currentScopes[0], currentConfig);

            /*
             * Each node has a type property. Whenever a particular type of node is found,
             * an event is fired. This allows any listeners to automatically be informed
             * that this type of node has been found and react accordingly.
             */
            controller.traverse(ast, {
                enter: function(node, parent) {
                    var comments = api.getComments(node),
                        leadingComments = comments.leading,
                        trailingComments = comments.trailing;

                    if (leadingComments.length) {
                        leadingComments.forEach(function(node) {
                            api.emit(node.type + "Comment", node);
                        });
                    }

                    node.parent = parent;

                    api.emit(node.type, node);

                    if (trailingComments.length) {
                        trailingComments.forEach(function(node) {
                            api.emit(node.type + "Comment", node);
                        });
                    }

                },
                leave: function(node) {

                    var comments = api.getComments(node),
                        leadingComments = comments.leading,
                        trailingComments = comments.trailing;

                    if (trailingComments.length) {
                        trailingComments.forEach(function(node) {
                            api.emit(node.type + "Comment:exit", node);
                        });
                    }

                    api.emit(node.type + ":exit", node);

                    if (leadingComments.length) {
                        leadingComments.forEach(function(node) {
                            api.emit(node.type + "Comment:exit", node);
                        });
                    }
                }
            });

        }

        return messages;
    };
コード例 #13
0
ファイル: eslint.js プロジェクト: chriswong/eslint
    api.verify = function(text, config, filename, saveState) {

        var ast,
            shebang;

        // set the current parsed filename
        currentFilename = filename;

        if (!saveState) {
            this.reset();
        }

        ast = parse(text.replace(/^#!([^\r\n]+)/, function(match, captured) {
            shebang = captured;
            return "//" + captured;
        }));

        // if Esprima failed to parse the file, there's no sense in setting up rules
        if (ast) {
            // process initial config to make it safe to extend
            config = prepareConfig(config);

            // parse global comments and modify config
            modifyConfigsFromComments(ast, config, reportingConfig);

            // enable appropriate rules
            Object.keys(config.rules).filter(function(key) {
                return getRuleSeverity(config.rules[key]) > 0;
            }).forEach(function(key) {

                var ruleCreator = rules.get(key),
                    severity = getRuleSeverity(config.rules[key]),
                    options = getRuleOptions(config.rules[key]),
                    rule;

                if (ruleCreator) {
                    try {
                        rule = ruleCreator(new RuleContext(key, api, severity, options, config.settings));

                        // add all the node types as listeners
                        Object.keys(rule).forEach(function(nodeType) {
                            api.on(nodeType, rule[nodeType]);
                        });
                    } catch(ex) {
                        ex.message = "Error while loading rule '" + key + "': " + ex.message;
                        throw ex;
                    }

                } else {
                    throw new Error("Definition for rule '" + key + "' was not found.");
                }
            });

            // save config so rules can access as necessary
            currentConfig = config;
            currentText = text;
            controller = new estraverse.Controller();

            // gather data that may be needed by the rules
            currentScopes = escope.analyze(ast, { ignoreEval: true }).scopes;

            /*
             * Index the scopes by the start range of their block for efficient
             * lookup in getScope.
             */
            scopeMap = [];
            currentScopes.forEach(function (scope, index) {
                var range = scope.block.range[0];

                // Sometimes two scopes are returned for a given node. This is
                // handled later in a known way, so just don't overwrite here.
                if (!scopeMap[range]) {
                    scopeMap[range] = index;
                }
            });

            /*
             * Split text here into array of lines so
             * it's not being done repeatedly
             * by individual rules.
             */
            currentTextLines = currentText.split(/\r?\n|\u2028|\u2029/g);

            // Freezing so array isn't accidentally changed by a rule.
            Object.freeze(currentTextLines);

            /* get all tokens from the ast and store them as a hashtable to
             * improve traversal speed when wanting to find tokens for a given
             * node
             */
            currentTokens = [];
            ast.tokens.forEach(function(token) {
                currentTokens[token.range[0]] = token;
            });

            // augment global scope with declared global variables
            addDeclaredGlobals(ast, currentScopes[0], currentConfig);

            // remove shebang comments
            if (shebang && ast.comments.length && ast.comments[0].value === shebang) {
                ast.comments.splice(0, 1);

                if (ast.body.length && ast.body[0].leadingComments && ast.body[0].leadingComments[0].value === shebang) {
                    ast.body[0].leadingComments.splice(0, 1);
                }
            }

            /*
             * Each node has a type property. Whenever a particular type of node is found,
             * an event is fired. This allows any listeners to automatically be informed
             * that this type of node has been found and react accordingly.
             */
            controller.traverse(ast, {
                enter: function(node, parent) {

                    var comments = api.getComments(node);

                    emitCommentsEnter(comments.leading);
                    node.parent = parent;
                    api.emit(node.type, node);
                    emitCommentsEnter(comments.trailing);
                },
                leave: function(node) {

                    var comments = api.getComments(node);

                    emitCommentsExit(comments.trailing);
                    api.emit(node.type + ":exit", node);
                    emitCommentsExit(comments.leading);
                }
            });

        }

        // sort by line and column
        messages.sort(function(a, b) {
            var lineDiff = a.line - b.line;

            if (lineDiff === 0) {
                return a.column - b.column;
            } else {
                return lineDiff;
            }
        });

        return messages;
    };
コード例 #14
0
ファイル: eslint.js プロジェクト: goatslacker/eslint
    api.verify = function(text, config, saveState) {

        var ast,
            parseError = false;

        if (!saveState) {
            this.reset();
        }

        // enable appropriate rules
        Object.keys(config.rules).filter(function(key) {
            if (typeof config.rules[key] === "number") {
                return config.rules[key] > 0;
            } else if (Array.isArray(config.rules[key])) {
                // Here the rule looks like [1, ...] - the first value is the key we want
                return config.rules[key][0] > 0;
            }
        }).forEach(function(key) {
            var ruleCreator = rules.get(key),
                options = [],
                rule;

            if (Array.isArray(config.rules[key])) {

                // The additional config data is after the bool value
                options = config.rules[key].slice(1);
            }

            if (ruleCreator) {
                rule = ruleCreator(new RuleContext(key, api, options));

                // add all the node types as listeners
                Object.keys(rule).forEach(function(nodeType) {
                    api.on(nodeType, rule[nodeType]);
                });
            } else {
                throw new Error("Definition for rule '" + key + "' was not found.");
            }
        });

        // save config so rules can access as necessary
        currentConfig = config;
        currentText = text;
        controller = new estraverse.Controller();

        /*
         * Check for parsing errors first. If there's a parsing error, nothing
         * else can happen. However, a parsing error does not throw an error
         * from this method - it's just considered a fatal error message, a
         * problem that ESLint identified just like any other.
         */
        try {
            ast = esprima.parse(text, { loc: true, range: true, raw: true, tokens: true });
        } catch (ex) {

            parseError = true;

            messages.push({
                fatal: true,

                // messages come as "Line X: Unexpected token foo", so strip off leading part
                message: ex.message.substring(ex.message.indexOf(":") + 1).trim(),

                line: ex.lineNumber,
                column: ex.column
            });
        }

        if (!parseError) {

            // gather data that may be needed by the rules
            currentScopes = escope.analyze(ast).scopes;
            currentTokens = ast.tokens;

            /*
             * Each node has a type property. Whenever a particular type of node is found,
             * an event is fired. This allows any listeners to automatically be informed
             * that this type of node has been found and react accordingly.
             */
            controller.traverse(ast, {
                enter: function(node) {
                    api.emit(node.type, node);
                },
                leave: function(node) {
                    api.emit(node.type + ":after", node);
                }
            });

        }

        return messages;
    };
コード例 #15
0
ファイル: eslint.js プロジェクト: mduvall/eslint
    api.verify = function(text, config, saveState) {

        var parseError = false,
            ast;

        if (!saveState) {
            this.reset();
        }

        /*
         * Check for parsing errors first. If there's a parsing error, nothing
         * else can happen. However, a parsing error does not throw an error
         * from this method - it's just considered a fatal error message, a
         * problem that ESLint identified just like any other.
         */
        try {
            ast = esprima.parse(text, { loc: true, range: true, raw: true, tokens: true, comment: true });
        } catch (ex) {

            parseError = true;

            messages.push({
                fatal: true,

                // messages come as "Line X: Unexpected token foo", so strip off leading part
                message: ex.message.substring(ex.message.indexOf(":") + 1).trim(),

                line: ex.lineNumber,
                column: ex.column
            });
        }

        //if Esprima failed to parse the file, there's no sense in setting up rules
        if (!parseError) {
            // parse global comments and modify config rules
            config.rules = modifyRulesFromComments(ast, config);

            // enable appropriate rules
            Object.keys(config.rules).filter(function(key) {
                if (typeof config.rules[key] === "number") {
                    return config.rules[key] > 0;
                } else if (Array.isArray(config.rules[key])) {
                    // Here the rule looks like [1, ...] - the first value is the key we want
                    return config.rules[key][0] > 0;
                }
            }).forEach(function(key) {
                var ruleCreator = rules.get(key),
                    options = [],
                    rule;

                if (Array.isArray(config.rules[key])) {

                    // The additional config data is after the bool value
                    options = config.rules[key].slice(1);
                }

                /* istanbul ignore else Too complicate to fake invalid rule*/
                if (ruleCreator) {
                    try {
                        rule = ruleCreator(new RuleContext(key, api, options));

                        // add all the node types as listeners
                        Object.keys(rule).forEach(function(nodeType) {
                            api.on(nodeType, rule[nodeType]);
                        });
                    } catch(ex) {
                        throw new Error("Error while loading rule '" + key + "'.");
                    }

                } else {
                    throw new Error("Definition for rule '" + key + "' was not found.");
                }
            });

            // save config so rules can access as necessary
            currentConfig = config;
            currentText = text;
            controller = new estraverse.Controller();

            // gather data that may be needed by the rules
            currentScopes = escope.analyze(ast, { ignoreEval: true }).scopes;

            /* get all tokens from the ast and store them as a hashtable to
             * improve traversal speed when wanting to find tokens for a given
             * node
             */
            currentTokens = [];
            ast.tokens.forEach(function(token) {
                currentTokens[token.range[0]] = token;
            });

            // augment global scope with declared global variables
            addDeclaredGlobals(ast, currentScopes[0], currentConfig);

            /*
             * Each node has a type property. Whenever a particular type of node is found,
             * an event is fired. This allows any listeners to automatically be informed
             * that this type of node has been found and react accordingly.
             */
            controller.traverse(ast, {
                enter: function(node) {
                    var comments = api.getComments(node),
                        leadingComments = comments.leading,
                        trailingComments = comments.trailing;

                    if (leadingComments) {
                        leadingComments.forEach(function(node) {
                            api.emit(node.type + "Comment", node);
                        });
                    }

                    api.emit(node.type, node);

                    if (trailingComments) {
                        trailingComments.forEach(function(node) {
                            api.emit(node.type + "Comment", node);
                        });
                    }

                },
                leave: function(node) {

                    var comments = api.getComments(node),
                        leadingComments = comments.leading,
                        trailingComments = comments.trailing;

                    if (trailingComments) {
                        trailingComments.forEach(function(node) {
                            api.emit(node.type + "Comment:after", node);
                        });
                    }

                    api.emit(node.type + ":after", node);

                    if (leadingComments) {
                        leadingComments.forEach(function(node) {
                            api.emit(node.type + "Comment:after", node);
                        });
                    }
                }
            });

        }

        return messages;
    };
コード例 #16
0
ファイル: eslint.js プロジェクト: mdarif/eslint
    api.verify = function(text, config, saveState) {

        if (!saveState) {
            this.reset();
        }

        // enable appropriate rules
        Object.keys(config.rules).filter(function(key) {
            return config.rules[key] > 0;   // ignore rules that are turned off
        }).forEach(function(key) {

            var ruleCreator = rules.get(key),
                rule;

            if (ruleCreator) {
                rule = ruleCreator(new RuleContext(key, api));

                // add all the node types as listeners
                Object.keys(rule).forEach(function(nodeType) {
                    api.on(nodeType, rule[nodeType]);
                });
            } else {
                throw new Error("Definition for rule '" + key + "' was not found.");
            }
        });

        // save config so rules can access as necessary
        currentConfig = config;
        currentText = text;
        controller = new estraverse.Controller();

        /*
         * Each node has a type property. Whenever a particular type of node is found,
         * an event is fired. This allows any listeners to automatically be informed
         * that this type of node has been found and react accordingly.
         */
        try {
            var ast = esprima.parse(text, { loc: true, range: true, raw: true, tokens: true });
            currentTokens = ast.tokens;
            controller.traverse(ast, {
                enter: function(node) {
                    api.emit(node.type, node);
                },
                leave: function(node) {
                    api.emit(node.type + ":after", node);
                }
            });

        } catch (ex) {
            messages.push({
                fatal: true,

                // messages come as "Line X: Unexpected token foo", so strip off leading part
                message: ex.message.substring(ex.message.indexOf(":") + 1).trim(),

                line: ex.lineNumber,
                column: ex.column
            });
        }

        return messages;
    };
コード例 #17
0
ファイル: eslint.js プロジェクト: DarkDare/eslint
    api.verify = function(textOrSourceCode, config, filenameOrOptions, saveState) {

        var ast,
            shebang,
            ecmaFeatures,
            ecmaVersion,
            allowInlineConfig,
            text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null;

        // evaluate arguments
        if (typeof filenameOrOptions === "object") {
            currentFilename = filenameOrOptions.filename;
            allowInlineConfig = filenameOrOptions.allowInlineConfig;
            saveState = filenameOrOptions.saveState;
        } else {
            currentFilename = filenameOrOptions;
        }

        if (!saveState) {
            this.reset();
        }

        // search and apply "eslint-env *".
        var envInFile = findEslintEnv(text || textOrSourceCode.text);
        if (envInFile) {
            if (!config || !config.env) {
                config = lodash.assign({}, config || {}, {env: envInFile});
            } else {
                config = lodash.assign({}, config);
                config.env = lodash.assign({}, config.env, envInFile);
            }
        }

        // process initial config to make it safe to extend
        config = prepareConfig(config || {});

        // only do this for text
        if (text !== null) {
            // there's no input, just exit here
            if (text.trim().length === 0) {
                sourceCode = new SourceCode(text, blankScriptAST);
                return messages;
            }

            ast = parse(
                stripUnicodeBOM(text).replace(/^#!([^\r\n]+)/, function(match, captured) {
                    shebang = captured;
                    return "//" + captured;
                }),
                config
            );

            if (ast) {
                sourceCode = new SourceCode(text, ast);
            }

        } else {
            sourceCode = textOrSourceCode;
            ast = sourceCode.ast;
        }

        // if espree failed to parse the file, there's no sense in setting up rules
        if (ast) {

            // parse global comments and modify config
            if (allowInlineConfig !== false) {
                config = modifyConfigsFromComments(currentFilename, ast, config, reportingConfig, messages);
            }

            // ensure that severities are normalized in the config
            ConfigOps.normalize(config);

            // enable appropriate rules
            Object.keys(config.rules).filter(function(key) {
                return getRuleSeverity(config.rules[key]) > 0;
            }).forEach(function(key) {
                var ruleCreator,
                    severity,
                    options,
                    rule;

                ruleCreator = rules.get(key);
                if (!ruleCreator) {
                    var replacementMsg = getRuleReplacementMessage(key);
                    if (replacementMsg) {
                        ruleCreator = createStubRule(replacementMsg);
                    } else {
                        ruleCreator = createStubRule("Definition for rule '" + key + "' was not found");
                    }
                    rules.define(key, ruleCreator);
                }

                severity = getRuleSeverity(config.rules[key]);
                options = getRuleOptions(config.rules[key]);

                try {
                    var ruleContext = new RuleContext(
                        key, api, severity, options,
                        config.settings, config.parserOptions, config.parser, ruleCreator.meta);
                    rule = ruleCreator.create ? ruleCreator.create(ruleContext) :
                        ruleCreator(ruleContext);

                    // add all the node types as listeners
                    Object.keys(rule).forEach(function(nodeType) {
                        api.on(nodeType, timing.enabled
                            ? timing.time(key, rule[nodeType])
                            : rule[nodeType]
                        );
                    });
                } catch (ex) {
                    ex.message = "Error while loading rule '" + key + "': " + ex.message;
                    throw ex;
                }
            });

            // save config so rules can access as necessary
            currentConfig = config;
            controller = new estraverse.Controller();

            ecmaFeatures = currentConfig.parserOptions.ecmaFeatures || {};
            ecmaVersion = currentConfig.parserOptions.ecmaVersion || 5;

            // gather data that may be needed by the rules
            scopeManager = escope.analyze(ast, {
                ignoreEval: true,
                nodejsScope: ecmaFeatures.globalReturn,
                impliedStrict: ecmaFeatures.impliedStrict,
                ecmaVersion: ecmaVersion,
                sourceType: currentConfig.parserOptions.sourceType || "script",
                childVisitorKeys: espree.VisitorKeys,
                fallback: "none"
            });
            currentScopes = scopeManager.scopes;

            /*
             * Index the scopes by the start range of their block for efficient
             * lookup in getScope.
             */
            scopeMap = [];
            currentScopes.forEach(function(scope, index) {
                var range = scope.block.range[0];

                // Sometimes two scopes are returned for a given node. This is
                // handled later in a known way, so just don't overwrite here.
                if (!scopeMap[range]) {
                    scopeMap[range] = index;
                }
            });

            // augment global scope with declared global variables
            addDeclaredGlobals(ast, currentScopes[0], currentConfig);

            // remove shebang comments
            if (shebang && ast.comments.length && ast.comments[0].value === shebang) {
                ast.comments.splice(0, 1);

                if (ast.body.length && ast.body[0].leadingComments && ast.body[0].leadingComments[0].value === shebang) {
                    ast.body[0].leadingComments.splice(0, 1);
                }
            }

            var eventGenerator = new NodeEventGenerator(api);
            eventGenerator = new CodePathAnalyzer(eventGenerator);
            eventGenerator = new CommentEventGenerator(eventGenerator, sourceCode);

            /*
             * Each node has a type property. Whenever a particular type of node is found,
             * an event is fired. This allows any listeners to automatically be informed
             * that this type of node has been found and react accordingly.
             */
            controller.traverse(ast, {
                enter: function(node, parent) {
                    node.parent = parent;
                    eventGenerator.enterNode(node);
                },
                leave: function(node) {
                    eventGenerator.leaveNode(node);
                },
                keys: espree.VisitorKeys
            });
        }

        // sort by line and column
        messages.sort(function(a, b) {
            var lineDiff = a.line - b.line;

            if (lineDiff === 0) {
                return a.column - b.column;
            } else {
                return lineDiff;
            }
        });

        return messages;
    };