View | Details | Raw Unified | Return to bug 422630
Collapse All | Expand All

(-)a/bundles/org.eclipse.orion.client.javascript/web/javascript/eslint/validator.js (-22 / +91 lines)
Lines 14-21 Link Here
14
	"eslint",
14
	"eslint",
15
	"orion/objects",
15
	"orion/objects",
16
	"javascript/astManager",
16
	"javascript/astManager",
17
	"javascript/finder"
17
	"javascript/finder",
18
], function(eslint, Objects, ASTManager, Finder) {
18
	'orion/Deferred'
19
], function(eslint, Objects, ASTManager, Finder, Deferred) {
19
	// Should have a better way of keeping this up-to-date with ./load-rules-async.js
20
	// Should have a better way of keeping this up-to-date with ./load-rules-async.js
20
	var config = {
21
	var config = {
21
		// 0:off, 1:warning, 2:error
22
		// 0:off, 1:warning, 2:error
Lines 173-201 Link Here
173
		 */
174
		 */
174
		computeProblems: function(editorContext, context) {
175
		computeProblems: function(editorContext, context) {
175
			var _self = this;
176
			var _self = this;
176
			return this.astManager.getAST(editorContext).then(function(ast) {
177
			switch(context.contentType) {
177
				var eslintErrors = [], error;
178
				case 'text/html': 
178
				try {
179
					return editorContext.getText().then(function(text) {
179
					eslintErrors = eslint.verify(ast, config);
180
						var blocks = _self._extractScriptBlocks(text);
180
				} catch (e) {
181
						var len = blocks.length;
181
					error = e;
182
						var allproblems = [];
182
				}
183
						for(var i = 0; i < len; i++) {
183
				var parseErrors = _self._extractParseErrors(ast);
184
							//we don't want to cache these ASTs so call into the private parse method of the manager
184
				var problems = []
185
							var block = blocks[i];
185
					.concat(eslintErrors)
186
							var ast = _self.astManager.parse(block.text);
186
					.concat(parseErrors)
187
							var problems = _self._validateAst(ast).problems;
187
					.map(toProblem);
188
							var len2 = problems.length;
188
				if (error && !parseErrors.length) {
189
							if(len2 > 0) {
189
					// Warn about ESLint failure
190
								for(var j = 0; j < len2; j++) {
190
					problems.push({
191
									//patch the start of the problem for the script block offset
191
						start: 0,
192
									problems[j].start += block.offset; 
192
						description: "ESLint could not validate this file because an error occurred: " + error.toString(),
193
									problems[j].end += block.offset; 
193
						severity: "error" //$NON-NLS-0$
194
								}
195
								allproblems = allproblems.concat(problems);
196
							}
197
						}
198
						return {problems: allproblems};
199
					});
200
				case 'application/javascript': 
201
					return this.astManager.getAST(editorContext).then(function(ast) {
202
						return _self._validateAst(ast);
203
					});
204
			}
205
		},
206
		
207
		/**
208
		 * @description Validates the given AST
209
		 * @function
210
		 * @private
211
		 * @param {Object} ast The AST
212
		 * @returns {Array|Object} The array of problem objects
213
		 */
214
		_validateAst: function(ast) {
215
			var eslintErrors = [], error;
216
			try {
217
				eslintErrors = eslint.verify(ast, config);
218
			} catch (e) {
219
				error = e;
220
			}
221
			var parseErrors = this._extractParseErrors(ast);
222
			var problems = []
223
				.concat(eslintErrors)
224
				.concat(parseErrors)
225
				.map(toProblem);
226
			if (error && !parseErrors.length) {
227
				// Warn about ESLint failure
228
				problems.push({
229
					start: 0,
230
					description: "ESLint could not validate this file because an error occurred: " + error.toString(),
231
					severity: "error" //$NON-NLS-0$
232
				});
233
			}
234
			return { problems: problems };
235
		},
236
		
237
		/**
238
		 * @description Computes the script blocks from an HTML file
239
		 * @function
240
		 * @private
241
		 * @param {String} buffer The file contents
242
		 * @returns {Object} An object of script block items {text, offset}
243
		 * @since 6.0
244
		 */
245
		_extractScriptBlocks: function(buffer) {
246
			var blocks = [];
247
			var script = '<script>';
248
			var scriptend = '<\/script>';
249
			//sanitize the buffer a bit first, probably bad for performance
250
			buffer = buffer.replace(/<\s*script\s*>/ig, script);
251
			buffer = buffer.replace(/<\s*\/script\s*>/ig, scriptend);
252
			var index = buffer.indexOf(script);
253
			var end;
254
			while(index > -1) {
255
				index += 8;
256
				end = buffer.indexOf(scriptend, index);
257
				if(end != index) {
258
					blocks.push({
259
						text: buffer.substring(index, end),
260
						offset: index
194
					});
261
					});
195
				}
262
				}
196
				return { problems: problems };
263
				index = buffer.indexOf(script, end);
197
			});
264
			}
265
			return blocks;
198
		},
266
		},
267
		
199
		/**
268
		/**
200
		 * @description Callback from orion.cm.managedservice
269
		 * @description Callback from orion.cm.managedservice
201
		 * @function
270
		 * @function
(-)a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPlugin.js (-1 / +1 lines)
Lines 127-133 Link Here
127
	 */
127
	 */
128
	provider.registerService(["orion.edit.validator", "orion.cm.managedservice"], new EslintValidator(astManager),  //$NON-NLS-0$  //$NON-NLS-1$
128
	provider.registerService(["orion.edit.validator", "orion.cm.managedservice"], new EslintValidator(astManager),  //$NON-NLS-0$  //$NON-NLS-1$
129
		{
129
		{
130
			contentType: ["application/javascript"],  //$NON-NLS-0$
130
			contentType: ["application/javascript", "text/html"],  //$NON-NLS-0$
131
			pid: 'eslint.config'  //$NON-NLS-0$
131
			pid: 'eslint.config'  //$NON-NLS-0$
132
		});
132
		});
133
133
(-)a/bundles/org.eclipse.orion.client.ui/web/plugins/jslintPlugin.js (-12 / +2 lines)
Lines 22-28 Link Here
22
	};
22
	};
23
	var validationOptions = DEFAULT_VALIDATION_OPTIONS;
23
	var validationOptions = DEFAULT_VALIDATION_OPTIONS;
24
	var isEnabledFor = {
24
	var isEnabledFor = {
25
		'application/javascript': false,
26
		'application/json': true,
25
		'application/json': true,
27
		'text/html': true
26
		'text/html': true
28
	};
27
	};
Lines 148-157 Link Here
148
		// ManagedService
147
		// ManagedService
149
		updated: function(properties) {
148
		updated: function(properties) {
150
			if (properties) {
149
			if (properties) {
151
				if (typeof properties.enabled === "boolean") {
152
					// At the moment this setting only controls .js files
153
					isEnabledFor['application/javascript'] = !!properties.enabled;
154
				}
155
				if (typeof properties.options === "string") {
150
				if (typeof properties.options === "string") {
156
					var options = properties.options;
151
					var options = properties.options;
157
					if (!/^\s*$/.test(options)) {
152
					if (!/^\s*$/.test(options)) {
Lines 230-236 Link Here
230
	var headers = {
225
	var headers = {
231
		name: "Orion JSLint Service",
226
		name: "Orion JSLint Service",
232
		version: "1.0",
227
		version: "1.0",
233
		description: "This plugin provides JSLint functionality for outlining and validating JavaScript code."
228
		description: "This plugin provides JSLint functionality for outlining and validating HTML and JSON code."
234
	};
229
	};
235
230
236
	var provider = new PluginProvider(headers);
231
	var provider = new PluginProvider(headers);
Lines 249-262 Link Here
249
		{	settings: [
244
		{	settings: [
250
				{	pid: 'jslint.config',
245
				{	pid: 'jslint.config',
251
					name: 'JSLint Validator',
246
					name: 'JSLint Validator',
252
					tags: 'validation javascript js jslint'.split(' '),
247
					tags: 'validation HTML JSON jslint'.split(' '),
253
					category: 'validation',
248
					category: 'validation',
254
					properties: [
249
					properties: [
255
						{	id: 'enabled',
256
							name: 'Use JSLint to check JavaScript code',
257
							defaultValue: true,
258
							type: 'boolean'
259
						},
260
						{	id: 'options',
250
						{	id: 'options',
261
							name: 'Options to pass to JSLint (/*jslint ..*/)',
251
							name: 'Options to pass to JSLint (/*jslint ..*/)',
262
							type: 'string'
252
							type: 'string'

Return to bug 422630