|
Lines 12-19
Link Here
|
| 12 |
/*global define*/ |
12 |
/*global define*/ |
| 13 |
define([ |
13 |
define([ |
| 14 |
"eslint", |
14 |
"eslint", |
| 15 |
"orion/objects" |
15 |
"orion/objects", |
| 16 |
], function(eslint, objects) { |
16 |
"orion/Deferred", |
|
|
17 |
"javascript/astManager" |
| 18 |
], function(eslint, Objects, Deferred, ASTManager) { |
| 17 |
// Should have a better way of keeping this up-to-date with ./load-rules-async.js |
19 |
// Should have a better way of keeping this up-to-date with ./load-rules-async.js |
| 18 |
var config = { |
20 |
var config = { |
| 19 |
// 0:off, 1:warning, 2:error |
21 |
// 0:off, 1:warning, 2:error |
|
Lines 27-32
Link Here
|
| 27 |
"missing-func-decl-doc": [0, 'decl'], //$NON-NLS-0$ //$NON-NLS-1$ |
29 |
"missing-func-decl-doc": [0, 'decl'], //$NON-NLS-0$ //$NON-NLS-1$ |
| 28 |
"missing-func-expr-doc": [0, 'expr'] //$NON-NLS-0$ //$NON-NLS-1$ |
30 |
"missing-func-expr-doc": [0, 'expr'] //$NON-NLS-0$ //$NON-NLS-1$ |
| 29 |
}, |
31 |
}, |
|
|
32 |
/** |
| 33 |
* @description Sets the given rule to the given enabled value |
| 34 |
* @function |
| 35 |
* @private |
| 36 |
* @param {String} ruleId The id of the rule to change |
| 37 |
* @param {Number} value The vlaue to set the rule to |
| 38 |
*/ |
| 30 |
setOption: function(ruleId, value) { |
39 |
setOption: function(ruleId, value) { |
| 31 |
if (typeof value === "number") { |
40 |
if (typeof value === "number") { |
| 32 |
if(Array.isArray(this.rules[ruleId])) { |
41 |
if(Array.isArray(this.rules[ruleId])) { |
|
Lines 43-48
Link Here
|
| 43 |
* @description Creates a new ESLintValidator |
52 |
* @description Creates a new ESLintValidator |
| 44 |
* @constructor |
53 |
* @constructor |
| 45 |
* @public |
54 |
* @public |
|
|
55 |
* @param {javascript.ASTManager} astManager The AST manager backing this validator |
| 46 |
* @returns {ESLintValidator} Returns a new validator |
56 |
* @returns {ESLintValidator} Returns a new validator |
| 47 |
*/ |
57 |
*/ |
| 48 |
function ESLintValidator(astManager) { |
58 |
function ESLintValidator(astManager) { |
|
Lines 91-96
Link Here
|
| 91 |
} else if (typeof e.index === "number") { //$NON-NLS-0$ |
101 |
} else if (typeof e.index === "number") { //$NON-NLS-0$ |
| 92 |
// Esprima parse error |
102 |
// Esprima parse error |
| 93 |
start = e.index; |
103 |
start = e.index; |
|
|
104 |
end = e.end ? e.end : start; |
| 94 |
} |
105 |
} |
| 95 |
var prob = { |
106 |
var prob = { |
| 96 |
description: e.message, |
107 |
description: e.message, |
|
Lines 101-130
Link Here
|
| 101 |
return prob; |
112 |
return prob; |
| 102 |
} |
113 |
} |
| 103 |
|
114 |
|
| 104 |
objects.mixin(ESLintValidator.prototype, { |
115 |
Objects.mixin(ESLintValidator.prototype, { |
| 105 |
/** |
116 |
/** |
| 106 |
* @descritpion Extracts any errors captured by the tolerant esprima parser and returns them |
117 |
* @descritpion Extracts any errors captured by the tolerant esprima parser and returns them |
| 107 |
* @function |
118 |
* @function |
| 108 |
* @private |
119 |
* @private |
| 109 |
* @param {esprima.ASTNode} ast The AST |
120 |
* @param {esprima.AST} ast The AST |
|
|
121 |
* @param {String} buffer the text form the editor |
| 122 |
* @param {Array} asterrors The parse problems in the AST |
| 110 |
* @returns {esprima.Error[]} The array of AST errors (if any) |
123 |
* @returns {esprima.Error[]} The array of AST errors (if any) |
| 111 |
*/ |
124 |
*/ |
| 112 |
_extractParseErrors: function(ast) { |
125 |
_extractParseErrors: function(ast, buffer, offsets) { |
| 113 |
var errors = [], errorMap = Object.create(null); |
126 |
var errors = [], errorMap = Object.create(null); |
| 114 |
(ast.errors || []).forEach(function(error) { |
127 |
var asterrors = ast.errors; |
| 115 |
var msg = error.message, match; |
128 |
if(asterrors) { |
| 116 |
// Errors come as 'Line nn: Unexpected foo'. Strip off the first part |
129 |
var len = asterrors.length; |
| 117 |
if ((match = /^Line \d+: /.exec(msg))) { |
130 |
for(var i = 0; i < len; i++) { |
| 118 |
error.message = msg = "Parse error: " + msg.substring(match.index + match[0].length) + "."; |
131 |
var error = asterrors[i]; |
|
|
132 |
var msg = error.message; |
| 133 |
if(errorMap[error.index] === msg) { |
| 134 |
continue; |
| 135 |
} |
| 136 |
errorMap[error.index] = msg; |
| 137 |
if(error.type) { |
| 138 |
switch(error.type) { |
| 139 |
case ASTManager.ErrorTypes.Unexpected: |
| 140 |
var token = buffer.substring(error.index, offsets[i] + error.column); |
| 141 |
error.message = msg = "Syntax error on token '"+token+"', delete this token."; |
| 142 |
error.end = offsets[i] + error.column; |
| 143 |
break; |
| 144 |
case ASTManager.ErrorTypes.EndOfInput: |
| 145 |
error.message = "Syntax error, incomplete statement."; |
| 146 |
var text = buffer.substring(offsets[i], error.index).replace(/\s\s*$/, ''); |
| 147 |
//tag the last char, maybe end of word, maybe bad punctuation |
| 148 |
error.index = offsets[i] + text.length-1; |
| 149 |
error.end = offsets[i] + text.length; |
| 150 |
break; |
| 151 |
} |
| 152 |
} |
| 153 |
errors.push(error); |
| 119 |
} |
154 |
} |
| 120 |
// Hack to filter out duplicate error produced by our esprima, having same index and message as previous error. |
155 |
} |
| 121 |
if (errorMap[error.index] === msg) { |
|
|
| 122 |
return; |
| 123 |
} |
| 124 |
errorMap[error.index] = msg; |
| 125 |
errors.push(error); |
| 126 |
}); |
| 127 |
return errors; |
156 |
return errors; |
|
|
157 |
}, |
| 158 |
/** |
| 159 |
* @description Computes the array of line start promises for parser errors |
| 160 |
* @function |
| 161 |
* @private |
| 162 |
* @param {orin.editor.EditorContext} editorContext The backing editor context |
| 163 |
* @param {Array} errors The array of parser errors |
| 164 |
* @returns {Array|orion.Promise} Returns the array of line start promises |
| 165 |
*/ |
| 166 |
_getLineStartPromises: function(editorContext, errors) { |
| 167 |
var promises = []; |
| 168 |
(errors || []).forEach(function(error) { |
| 169 |
if(error.lineNumber) { |
| 170 |
promises.push(editorContext.getLineStart(error.lineNumber-1)); |
| 171 |
} |
| 172 |
}); |
| 173 |
return promises; |
| 128 |
}, |
174 |
}, |
| 129 |
/** |
175 |
/** |
| 130 |
* @descripion Callback to create problems from orion.edit.validator |
176 |
* @descripion Callback to create problems from orion.edit.validator |
|
Lines 137-149
Link Here
|
| 137 |
computeProblems: function(editorContext, context) { |
183 |
computeProblems: function(editorContext, context) { |
| 138 |
var _self = this; |
184 |
var _self = this; |
| 139 |
return this.astManager.getAST(editorContext).then(function(ast) { |
185 |
return this.astManager.getAST(editorContext).then(function(ast) { |
|
|
186 |
var deferred = new Deferred(); |
| 187 |
var promises = [deferred.resolve(ast), editorContext.getText()] |
| 188 |
.concat(_self._getLineStartPromises(editorContext, ast.errors)); |
| 189 |
return new Deferred.all(promises); |
| 190 |
}).then(function(results) { |
| 140 |
var eslintErrors = [], error; |
191 |
var eslintErrors = [], error; |
| 141 |
try { |
192 |
try { |
| 142 |
eslintErrors = eslint.verify(ast, config); |
193 |
eslintErrors = eslint.verify(results[0], config); |
| 143 |
} catch (e) { |
194 |
} catch (e) { |
| 144 |
error = e; |
195 |
error = e; |
| 145 |
} |
196 |
} |
| 146 |
var parseErrors = _self._extractParseErrors(ast); |
197 |
var parseErrors = _self._extractParseErrors(results[0], results[1], results.splice(2, results.length)); |
| 147 |
var problems = [] |
198 |
var problems = [] |
| 148 |
.concat(eslintErrors) |
199 |
.concat(eslintErrors) |
| 149 |
.concat(parseErrors) |
200 |
.concat(parseErrors) |