Commit | Line | Data |
---|---|---|
837afb80 TD |
1 | (function(mod) { |
2 | if (typeof exports == "object" && typeof module == "object") // CommonJS | |
3 | mod(require("../../lib/codemirror")); | |
4 | else if (typeof define == "function" && define.amd) // AMD | |
5 | define(["../../lib/codemirror"], mod); | |
6 | else // Plain browser env | |
7 | mod(CodeMirror); | |
8 | })(function(CodeMirror) { | |
9 | "use strict"; | |
10 | // declare global: JSHINT | |
77b7b761 TD |
11 | |
12 | var bogus = [ "Dangerous comment" ]; | |
13 | ||
14 | var warnings = [ [ "Expected '{'", | |
15 | "Statement body should be inside '{ }' braces." ] ]; | |
16 | ||
17 | var errors = [ "Missing semicolon", "Extra comma", "Missing property name", | |
18 | "Unmatched ", " and instead saw", " is not defined", | |
19 | "Unclosed string", "Stopping, unable to continue" ]; | |
20 | ||
837afb80 | 21 | function validator(text, options) { |
77b7b761 TD |
22 | JSHINT(text, options); |
23 | var errors = JSHINT.data().errors, result = []; | |
24 | if (errors) parseErrors(errors, result); | |
25 | return result; | |
26 | } | |
27 | ||
837afb80 | 28 | CodeMirror.registerHelper("lint", "javascript", validator); |
77b7b761 TD |
29 | |
30 | function cleanup(error) { | |
31 | // All problems are warnings by default | |
32 | fixWith(error, warnings, "warning", true); | |
33 | fixWith(error, errors, "error"); | |
34 | ||
35 | return isBogus(error) ? null : error; | |
36 | } | |
37 | ||
38 | function fixWith(error, fixes, severity, force) { | |
39 | var description, fix, find, replace, found; | |
40 | ||
41 | description = error.description; | |
42 | ||
43 | for ( var i = 0; i < fixes.length; i++) { | |
44 | fix = fixes[i]; | |
45 | find = (typeof fix === "string" ? fix : fix[0]); | |
46 | replace = (typeof fix === "string" ? null : fix[1]); | |
47 | found = description.indexOf(find) !== -1; | |
48 | ||
49 | if (force || found) { | |
50 | error.severity = severity; | |
51 | } | |
52 | if (found && replace) { | |
53 | error.description = replace; | |
54 | } | |
55 | } | |
56 | } | |
57 | ||
58 | function isBogus(error) { | |
59 | var description = error.description; | |
60 | for ( var i = 0; i < bogus.length; i++) { | |
61 | if (description.indexOf(bogus[i]) !== -1) { | |
62 | return true; | |
63 | } | |
64 | } | |
65 | return false; | |
66 | } | |
67 | ||
68 | function parseErrors(errors, output) { | |
69 | for ( var i = 0; i < errors.length; i++) { | |
70 | var error = errors[i]; | |
71 | if (error) { | |
72 | var linetabpositions, index; | |
73 | ||
74 | linetabpositions = []; | |
75 | ||
76 | // This next block is to fix a problem in jshint. Jshint | |
77 | // replaces | |
78 | // all tabs with spaces then performs some checks. The error | |
79 | // positions (character/space) are then reported incorrectly, | |
80 | // not taking the replacement step into account. Here we look | |
81 | // at the evidence line and try to adjust the character position | |
82 | // to the correct value. | |
83 | if (error.evidence) { | |
84 | // Tab positions are computed once per line and cached | |
85 | var tabpositions = linetabpositions[error.line]; | |
86 | if (!tabpositions) { | |
87 | var evidence = error.evidence; | |
88 | tabpositions = []; | |
89 | // ugggh phantomjs does not like this | |
90 | // forEachChar(evidence, function(item, index) { | |
91 | Array.prototype.forEach.call(evidence, function(item, | |
92 | index) { | |
93 | if (item === '\t') { | |
94 | // First col is 1 (not 0) to match error | |
95 | // positions | |
96 | tabpositions.push(index + 1); | |
97 | } | |
98 | }); | |
99 | linetabpositions[error.line] = tabpositions; | |
100 | } | |
101 | if (tabpositions.length > 0) { | |
102 | var pos = error.character; | |
103 | tabpositions.forEach(function(tabposition) { | |
104 | if (pos > tabposition) pos -= 1; | |
105 | }); | |
106 | error.character = pos; | |
107 | } | |
108 | } | |
109 | ||
110 | var start = error.character - 1, end = start + 1; | |
111 | if (error.evidence) { | |
112 | index = error.evidence.substring(start).search(/.\b/); | |
113 | if (index > -1) { | |
114 | end += index; | |
115 | } | |
116 | } | |
117 | ||
118 | // Convert to format expected by validation service | |
119 | error.description = error.reason;// + "(jshint)"; | |
120 | error.start = error.character; | |
121 | error.end = end; | |
122 | error = cleanup(error); | |
123 | ||
124 | if (error) | |
125 | output.push({message: error.description, | |
126 | severity: error.severity, | |
127 | from: CodeMirror.Pos(error.line - 1, start), | |
128 | to: CodeMirror.Pos(error.line - 1, end)}); | |
129 | } | |
130 | } | |
131 | } | |
837afb80 | 132 | }); |