source: Dev/branches/rest-dojo-ui/client/util/checkstyle/checkstyleUtil.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 24.1 KB
Line 
1checkstyleUtil = {
2        errors: [],
3       
4        commentNames: ["summary", "description", "example", "tags", "this"]
5};
6
7checkstyleUtil.applyRules = function(fileName, contents){
8        // Do not process JSON files
9        if(contents.charAt(0) == "{"){
10                return;
11        }
12       
13        // Mark all the characters that are in comments.
14        var comments = checkstyleUtil.getComments(contents);
15       
16        // Apply all the rules to the file
17        for(var ruleName in checkstyleUtil.rules){
18                checkstyleUtil.rules[ruleName](fileName, contents, comments);
19        }
20};
21
22// Calculate the characters in a file that are in comment fields
23// These will be ignored by the checkstyle rules.
24checkstyleUtil.getComments = function(contents){
25        var comments = [];
26       
27        var i;
28       
29        // Initialize the array to false values.
30        for(i = 0; i < contents.length; i++){
31                comments[i] = 0;
32        }
33       
34        var sep = "\n";
35       
36        function markRange(start, stop){
37                for(var i = start; i < stop; i++){
38                        comments[i] = 1;
39                }
40        }
41
42
43        function markRegexs() {
44                var idx = contents.indexOf("/g");
45                var i;
46                while(idx > -1) {
47                        if(!comments[idx] && contents.charAt(idx - 1) != "*"){
48                                // Look back until either a forward slash
49                                // or a new line is found
50                                var prevChar = contents.charAt(idx - 1);
51                                i = idx;
52                                while(prevChar != "\n" && prevChar != "/" && i > 0){
53                                        prevChar = contents.charAt(--i);
54                                }
55                                if(prevChar == "/" && i < idx - 1){
56                                        markRange(i, idx);
57                                }
58                        }
59                        idx = contents.indexOf("/g", idx + 2)
60                }
61               
62                // Now mark all .match and .replace function calls
63                // They generally contain regular expressions, and are just too bloody difficult.
64                var fnNames = ["match", "replace"];
65                var name;
66               
67                for (i = 0; i < fnNames.length; i++){
68                        name = fnNames[i];
69                       
70                        idx = contents.indexOf(name + "(");
71                       
72                        while(idx > -1){
73                                // Find the end parenthesis
74                                if(comments[idx]){
75                                        idx = contents.indexOf(name + "(", idx + name.length);
76                                } else {
77                                        var fnEnd = contents.indexOf(")", idx);
78                                        markRange(idx, fnEnd + 1);
79                                }
80                        }
81                }
82               
83                // Now look for all the lines that declare a regex variable, e.g.
84                // var begRegExp = /^,|^NOT |^AND |^OR |^\(|^\)|^!|^&&|^\|\|/i;
85               
86                idx = contents.indexOf(" = /");
87               
88                while(idx > -1){
89                        if(!comments[idx] && contents.charAt(idx + 4) != "*"){
90                                var eol = contents.indexOf("\n", idx + 1);
91                                markRange(idx + 3, Math.max(eol, idx + 4));
92                        }
93               
94                        idx = contents.indexOf(" = /", idx + 3);
95                }
96        }
97
98        markRegexs();
99       
100       
101        var marker = null;
102        var ch;
103       
104        var DOUBLE_QUOTE = 1;
105        var SINGLE_QUOTE = 2;
106        var LINE_COMMENT = 3;
107        var MULTI_COMMENT = 4;
108        var UNMARK = 5;
109       
110        var pos;
111       
112        for (i = 0; i < contents.length; i++) {
113                var skip = false;
114               
115                if(comments[i]){
116                        continue;
117                }
118               
119                ch = contents[i];
120               
121                switch(ch){
122                        case "\"":
123                                if(marker == DOUBLE_QUOTE) {
124                                        marker = UNMARK;
125                                } else if (marker == null) {
126                                        marker = DOUBLE_QUOTE;
127                                        pos = i;
128                                }
129                               
130                                break;
131                        case "'":
132                                if(marker == SINGLE_QUOTE) {
133                                        marker = UNMARK;
134                                } else if (marker == null) {
135                                        marker = SINGLE_QUOTE;
136                                        pos = i;
137                                }
138                       
139                                break;
140                        case "/":
141                                if(marker == null){
142                                        if(contents[i + 1] == "/"){
143                                                marker = LINE_COMMENT;
144                                                pos = i;
145                                                skip = true;
146                                        } else if(contents[i + 1] == "*"){
147                                                marker = MULTI_COMMENT;
148                                                pos = i;
149                                                skip = true;
150                                        }
151                                }
152                               
153                                break;
154                        case "*":
155                                if (marker == MULTI_COMMENT){
156                                        if(contents[i + 1] == "/"){
157                                                marker = UNMARK;
158                                                skip = true;
159                                        }
160                                }
161                       
162                                break;
163                        case "\n":
164                                if(marker == LINE_COMMENT){
165                                        marker = UNMARK;
166                                }
167                                break;
168               
169                }
170                if (marker != null) {
171                        comments[i] = 1;
172                }
173                if (marker == UNMARK){
174                        marker = null;
175                }
176                if  (skip) {
177                        i++;
178                        comments[i] = 1;
179                }
180        }
181       
182       
183        return comments;
184}
185
186// Calculate the line number of the character at index 'pos'
187checkstyleUtil.getLineNumber = function(contents, pos){
188        var counter = 0;
189        var sep = "\n";
190               
191        for(var i = pos; i > -1; i--){
192                if(contents.charAt(i) == "\n"){
193                        counter ++;
194                }
195        }
196        return counter + 1;
197};
198
199// Store the information for a single error.
200checkstyleUtil.addError = function(msg, fileName, contents, pos){
201        while(fileName.indexOf("../") == 0){
202                fileName = fileName.substring(3);
203        }
204        checkstyleUtil.errors.push({
205                file: fileName,
206                line: checkstyleUtil.getLineNumber(contents, pos),
207                message: msg
208        });
209};
210
211// Find the next character in 'contents' after the index 'start'
212// Spaces and tabs are ignored.
213checkstyleUtil.getNextChar = function(contents, start, comments, ignoreNewLine){
214        for(var i = start; i < contents.length; i++){
215                if(comments && comments[i]){
216                        continue;
217                }
218                if(contents.charAt(i) != " "
219                        && contents.charAt(i) != "\t"
220                        && (!ignoreNewLine || contents.charCodeAt(i) != 13)){
221                        return {
222                                value: contents[i],
223                                pos: i
224                        };
225                }
226        }
227        return null;
228};
229
230// Find the next occurrence of the character in the
231// 'contents' array after the index 'start'
232checkstyleUtil.findNextCharPos = function(contents, start, character){
233        for(var i = start; i < contents.length; i++){
234                if(contents.charAt(i) == character){
235                        return i;
236                }
237        }
238        return -1;
239};
240
241// Creates a simple function that searches for the token, and
242// adds an error if it is found
243checkstyleUtil.createSimpleSearch = function(token, message){
244        return function(fileName, contents, comments){
245                var idx = contents.indexOf(token);
246               
247                while(idx > -1){
248                       
249                        if(!comments[idx]){
250                                checkstyleUtil.addError(message, fileName, contents, idx);
251                        }
252                        idx = contents.indexOf(token, idx + 1);
253                }
254        };
255};
256
257// Creates a function that fails a test if the given token
258// does not have a space to the left and right.
259checkstyleUtil.createSpaceWrappedSearch = function(token, message){
260        return function(fileName, contents, comments){
261               
262                var idx = contents.indexOf(token);
263                var before, after;
264                var tokenLength = token.length;
265
266                while(idx > -1){
267                        before = contents.charAt(idx - 1);
268                        after = contents.charAt(idx + tokenLength);
269                        if(!comments[idx] &&
270                                ((before != " " && before != "\t"
271                                        && (token != "==" || before != "!")
272                                        && (token != "=" ||
273                                                (before != "<" &&
274                                                 before != ">" &&
275                                                 before != "=" &&
276                                                 before != "!" &&
277                                                 before != "+" &&
278                                                 before != "-" &&
279                                                 before != "*" &&
280                                                 before != "/" &&
281                                                 before != "&" &&
282                                                 before != "|" ))) ||
283                                (
284                                        (after != " " && contents.charCodeAt(idx + tokenLength) != 13
285                                                && contents.charCodeAt(idx + tokenLength) != 10)
286                                        && (token != "==" || after != "=")
287                                        && (token != "!=" || after != "=")
288                                        && (token != "<" || after != "=")
289                                        && (token != ">" || after != "=")
290                                        && (token != "=" || after != "=")
291                                        && (token != "&" || after != "=")
292                                        && (token != "|" || after != "=")
293                                        && (token != "+" || after != "=")
294                                        && (token != "-" || after != "=")
295                                        && (token != "*" || after != "=")
296                                        && (token != "/" || after != "=")
297                                ))){
298                                checkstyleUtil.addError(message, fileName, contents, idx);
299                        }
300                        idx = contents.indexOf(token, idx + token.length);
301                }
302        };
303};
304
305
306
307checkstyleUtil.isEOL = function(contents, pos){
308        var c = contents.charCodeAt(pos);
309        return c == 10 || c == 13 || contents.charAt(pos) == "\n";
310};
311
312// All the rules that will be applied to each file.
313checkstyleUtil.rules = {
314
315        "elseFollowedBySpace": function(fileName, contents, comments){
316                var idx = contents.indexOf("else ");
317                while(idx > -1){
318
319                        if(!comments[idx] && contents.substring(idx + 5, idx + 7) != "if"){
320                                checkstyleUtil.addError("\" else \" cannot be followed by a space", fileName, contents, idx);
321                        }
322                        idx = contents.indexOf("else {", idx + 1);
323                }
324        },
325       
326        "trailingComma" : function(fileName, contents, comments){
327               
328                var s = ",";
329                var idx = contents.indexOf(s);
330                var nextChar;
331               
332                while(idx > -1){
333                        if(!comments[idx]){
334                                nextChar = checkstyleUtil.getNextChar(contents, idx + 1, comments, true);
335                                if(nextChar && nextChar.value == "}"){
336                                        checkstyleUtil.addError("Trailing commas are not permitted", fileName, contents, idx);
337                                }
338                        }
339                        idx = contents.indexOf(s, idx + 1);
340                }
341        },
342       
343        "switchCaseNewLine" : function(fileName, contents, comments){
344                var s = "\tcase ";
345                var idx = contents.indexOf(s);
346                var nextColonIdx;
347                var eolIdx;
348               
349                while(idx > -1){
350                       
351                        if(!comments[idx]){
352                                eolIdx = contents.indexOf("\n", idx + 4);
353                               
354                                if(eolIdx > idx){
355                                        // Count backwards from the end of the line.
356                                        // The first character, that is not a comment,
357                                        // Should be a ':'
358                                       
359                                        for(var i = eolIdx; i > idx + 4; i--){
360                                                var c = contents.charAt(i);
361                                                if(!comments[i]
362                                                        && c != ' '
363                                                        && c != '\t'
364                                                        && c != ':'
365                                                        && !checkstyleUtil.isEOL(contents, i)){
366                                                        checkstyleUtil.addError(
367                                                                "A CASE statement should be followed by a new line",
368                                                                fileName, contents, idx);
369                                                        break;
370                                                }
371                                                if(c == ':'){
372                                                        break;
373                                                }
374                                        }
375                                }
376                        }
377                        idx = contents.indexOf(s, idx + 4);
378                }
379        },
380       
381        "curlyBraceAtStartOfLine": function(fileName, contents, comments){
382               
383                var idx = contents.indexOf("\n");
384               
385                while(idx > -1){
386                        var nextChar = checkstyleUtil.getNextChar(contents, idx + 1);
387                       
388                        if(nextChar && !comments[nextChar.pos] && nextChar.value == "{"){
389                                // Go back three lines, and look for "dojo.declare".  If it exists in the last three lines,
390                                // then it is ok to have  { at the start of this line.
391                               
392                                var nlCount = 0;
393                                var i;
394                                for(i = idx - 1; i > -1 && nlCount < 3; i--){
395                                        if(contents[i] == "\n"){
396                                                nlCount++;
397                                        }
398                                }
399                                var declarePos = contents.indexOf("dojo.declare", Math.max(0, i));
400                                if(declarePos < 0 || declarePos > idx){
401                                        checkstyleUtil.addError("An opening curly brace should not be the first on a line", fileName, contents, idx);
402                                }
403                        }
404                        idx = contents.indexOf("\n", idx + 1);
405                }
406        },
407       
408        "parenthesisSpaceCurlyBrace": checkstyleUtil.createSimpleSearch(") {", "A space is not permitted between a closing parenthesis and a curly brace"),
409       
410        "useTabs": function(fileName, contents, comments){
411               
412                var idx = contents.indexOf("  ");
413               
414                while(idx > -1){
415                        var nextChar = checkstyleUtil.getNextChar(contents, idx + 1);
416                        if(!comments[idx] && nextChar && nextChar.value.charCodeAt(0) != 13){
417                                checkstyleUtil.addError("Tabs should be used instead of spaces", fileName, contents, idx);
418                                var nextLine = checkstyleUtil.findNextCharPos(contents, idx + 1, "\n");
419                                if(nextLine < 0){
420                                        break;
421                                }
422                                idx = contents.indexOf("  ", nextLine + 1);
423                        } else{
424                                idx = contents.indexOf("  ", idx + 2);
425                        }
426                }
427        },
428       
429        "commentFormatting": function(fileName, contents, comments){
430               
431                var commentNames = checkstyleUtil.commentNames;
432                var invalidPrefixes = ["//", "//\t"];
433                var idx;
434               
435                for(var i = 0; i < commentNames.length; i++){
436                        var comment = commentNames[i];
437
438                        for(var j = 0; j < invalidPrefixes.length; j++){
439                                idx = contents.indexOf(invalidPrefixes[j] + comment + ":");
440
441                                // Make sure that there is a space before the comment.
442                                while(idx > -1){
443                                        checkstyleUtil.addError("Must be just a space in a comment before \"" + comment + "\"" , fileName, contents, idx);
444                                        var nextLine = checkstyleUtil.findNextCharPos(contents, idx + 1, "\n");
445                                        if(nextLine < 0){
446                                                break;
447                                        }
448                                        idx = contents.indexOf(invalidPrefixes[j] + comment + ":", nextLine);
449                                }
450                        }
451                       
452                        idx = contents.indexOf(comment + ":");
453                       
454                        // Make sure that the comment name is on a line by itself. The body of the comment
455                        // must be on the next line.
456                        while(idx > -1){
457                                if(comments[idx]){
458                                        var search = idx + comment.length + 1;
459                               
460                                        // Make sure that there is nothing after the comment name on the same line.
461                                        while(!checkstyleUtil.isEOL(contents, search)){
462                                                if(contents[search] != " " && contents[search] != "\t"){
463                                                        checkstyleUtil.addError("The comment \"" + comment + "\" must be followed by a new line" ,
464                                                                                fileName, contents, idx);
465                                                        break;
466                                                }
467                                                search++;
468                                        }
469                                }
470                                idx = contents.indexOf(comment + ":", idx + comment.length + 2);
471                        }
472                }
473        },
474       
475        "spacesAroundEquals": checkstyleUtil.createSpaceWrappedSearch("==", "The equals sign should be preceded and followed by a space"),
476        "spacesAroundNotEquals": checkstyleUtil.createSpaceWrappedSearch("!=", "The != sign should be preceded and followed by a space"),
477        "spacesAroundAssignment": checkstyleUtil.createSpaceWrappedSearch("=", "The = sign should be preceded and followed by a space"),
478        "spacesAroundOr": checkstyleUtil.createSpaceWrappedSearch("||", "The || sign should be preceded and followed by a space"),
479        "spacesAroundLessThan": checkstyleUtil.createSpaceWrappedSearch("<", "The < sign should be preceded and followed by a space"),
480        "spacesAroundGreaterThan": checkstyleUtil.createSpaceWrappedSearch(">", "The > sign should be preceded and followed by a space"),
481        "spacesAroundAnd": checkstyleUtil.createSpaceWrappedSearch("&&", "The && sign should be preceded and followed by a space")
482};
483
484var noSpaceAfter = ["catch","do","finally","for","if","switch","try","while","with"];
485
486// Add checks for all the elements that are not allowed to have a space after them.
487checkstyleUtil.createNoSpaceAfterFunction = function(name){
488        checkstyleUtil.rules["noSpaceAfter" + noSpaceAfter[i] + "1"] =
489                checkstyleUtil.createSimpleSearch(" " + name +" ", "\" " + name + " \" cannot be followed by a space");
490        checkstyleUtil.rules["noSpaceAfter" + noSpaceAfter[i] + "2"] =
491                checkstyleUtil.createSimpleSearch("\t" + name +" ", "\" " + name + " \" cannot be followed by a space");
492}
493
494for(var i = 0; i < noSpaceAfter.length; i++){
495        checkstyleUtil.createNoSpaceAfterFunction(noSpaceAfter[i]);
496}
497
498checkstyleUtil.clear = function(){
499        checkstyleUtil.errors = [];
500}
501
502checkstyleUtil.serializeErrors = function(){
503        var buf = [];
504        var errs = checkstyleUtil.errors;
505        for(var i = 0; i < errs.length; i++){
506                buf.push(errs[i].file + ":" + errs[i].line + " - " + errs[i].message);
507        }
508        return buf.join("\n");
509}
510
511checkstyleUtil.makeSimpleFixes = function(contents){
512       
513        var comments = checkstyleUtil.getComments(contents);
514        for(var i = 0; i < noSpaceAfter.length; i++){
515                contents = checkstyleUtil.fixSpaceAfter(contents, noSpaceAfter[i], comments);
516        }
517        /*
518        contents = contents.split("    ").join("\t")
519                                .split("  ").join("\t")
520                                .split(") {").join("){")
521                                .split("\tif (").join("\tif(")
522                                .split("} else").join("}else")
523                                .split("}\telse").join("}else")
524                                .split("}else {").join("}else{")
525                                .split("\twhile (").join("\twhile(")
526                                .split("\tfor (").join("\tfor(")
527                                .split("\tswitch (").join("\tswitch(");
528        */
529       
530        contents = checkstyleUtil.replaceAllExceptComments(contents, "=  ", "= ", comments);
531        comments = checkstyleUtil.getComments(contents);
532        contents = checkstyleUtil.replaceAllExceptComments(contents, "    ", "\t", comments);
533        comments = checkstyleUtil.getComments(contents);
534        contents = checkstyleUtil.replaceAllExceptComments(contents, "  ", "\t", comments);
535        comments = checkstyleUtil.getComments(contents);
536        contents = checkstyleUtil.replaceAllExceptComments(contents, "\tif (", "\tif(", comments);
537        comments = checkstyleUtil.getComments(contents);
538        contents = checkstyleUtil.replaceAllExceptComments(contents, "} else", "}else", comments);
539        comments = checkstyleUtil.getComments(contents);
540        contents = checkstyleUtil.replaceAllExceptComments(contents, "}\telse", "}else", comments);
541        comments = checkstyleUtil.getComments(contents);
542        contents = checkstyleUtil.replaceAllExceptComments(contents, "}else {", "}else{", comments);
543        comments = checkstyleUtil.getComments(contents);
544        contents = checkstyleUtil.replaceAllExceptComments(contents, "\twhile (", "\twhile(", comments);
545        comments = checkstyleUtil.getComments(contents);
546        contents = checkstyleUtil.replaceAllExceptComments(contents, "\tfor (", "\tfor(", comments);
547        comments = checkstyleUtil.getComments(contents);
548        contents = checkstyleUtil.replaceAllExceptComments(contents, "\tswitch (", "\tswitch(", comments);
549        comments = checkstyleUtil.getComments(contents);
550        contents = checkstyleUtil.replaceAllExceptComments(contents, ") {", "){", comments);
551        comments = checkstyleUtil.getComments(contents);
552        contents = checkstyleUtil.replaceAllExceptComments(contents, "//summary:", "// summary:", {});
553        contents = checkstyleUtil.replaceAllExceptComments(contents, "//description:", "// description:", {});
554        comments = checkstyleUtil.getComments(contents);
555       
556        contents = checkstyleUtil.fixTrailingWhitespace(contents);
557        comments = checkstyleUtil.getComments(contents);
558        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "===", comments);
559        comments = checkstyleUtil.getComments(contents);
560        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "!==", comments);
561        comments = checkstyleUtil.getComments(contents);
562        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "<=", comments);
563        comments = checkstyleUtil.getComments(contents);
564        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "<", comments);
565        comments = checkstyleUtil.getComments(contents);
566        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, ">=", comments);
567        comments = checkstyleUtil.getComments(contents);
568        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, ">", comments);
569        comments = checkstyleUtil.getComments(contents);
570        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "!=", comments);
571        comments = checkstyleUtil.getComments(contents);
572        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "==", comments);
573        comments = checkstyleUtil.getComments(contents);
574        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "=", comments);
575        comments = checkstyleUtil.getComments(contents);
576        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "||", comments);
577        comments = checkstyleUtil.getComments(contents);
578        contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "&&", comments);
579        comments = checkstyleUtil.getComments(contents);
580       
581        contents = checkstyleUtil.fixCommentNames(contents);
582       
583       
584       
585        return contents;
586}
587
588checkstyleUtil.fixCommentNames = function(contents){
589        var commentNames = checkstyleUtil.commentNames;
590        var i;
591       
592        for(i = 0; i < commentNames.length; i++){
593                contents = checkstyleUtil.replaceAllExceptComments(contents, "//\t" + commentNames[i] + ":", "// " + commentNames[i] + ":", {});
594        }
595       
596        for(i = 0; i < commentNames.length; i++){
597                var commentName = commentNames[i];
598                var searchToken = "// " + commentName + ":";
599                var idx = contents.indexOf(searchToken);
600               
601               
602                while(idx > -1){
603                        // If the comment name is not followed immediately by a new line, then insert a new line,
604                        // two forward slashes and two tabs.
605                        if(!checkstyleUtil.isEOL(contents, idx + commentName.length + 4)){
606                                // Calculate how many tabs to put before the "//"
607                               
608                                var tabs = "";
609                                var search = idx - 1;
610                                while(!checkstyleUtil.isEOL(contents, search)){
611                                        tabs += contents.charAt(search);
612                                        search--;
613                                }
614                                var insertPos = idx + commentName.length + 4;
615                                if(contents.charAt(insertPos) == " " || contents.charAt(insertPos) == "\t"){
616                                        contents = checkstyleUtil.deleteChar(contents, insertPos);
617                                }
618                               
619                                contents = checkstyleUtil.insertChar(contents, "\n" + tabs + "//\t\t", idx + commentName.length + 4);
620                       
621                        }
622                        idx = contents.indexOf(searchToken, idx + commentName.length);
623                }
624        }
625        return contents;
626}
627
628
629checkstyleUtil.replaceAllExceptComments = function(contents, old, newStr, comments){
630        var idx = contents.indexOf(old);
631        var toRemove = [];
632       
633        while(idx > -1){
634                if(!comments[idx]){
635                        toRemove.push(idx);
636                }
637
638                idx = contents.indexOf(old, idx + old.length);
639        }
640       
641        // Process the string backwards so we don't have to recompute the comments each time.
642        for(var i = toRemove.length - 1; i > -1; i--){
643                idx = toRemove[i];
644                if(!comments[idx]){
645                        contents = contents.substring(0, idx)
646                                        + newStr
647                                        + contents.substring(idx + old.length, contents.length);
648                }
649        }
650        return contents;
651}
652
653checkstyleUtil.insertChar = function(contents, ch, pos){
654        return contents.substring(0, pos) + ch + contents.substring(pos);
655}
656checkstyleUtil.deleteChar = function(contents, pos){
657        return contents.substring(0, pos) + contents.substring(pos + 1);
658}
659
660checkstyleUtil.fixTrailingWhitespace = function(contents) {
661        var idx = contents.indexOf("\n");
662       
663        // Find each new line character, then iterate backwards until a non-whitespace character is found
664        // then remove the whitespace.
665        while(idx > -1){
666                var search = idx - 1;
667               
668                while(search > -1 && (contents.charAt(search) == " " || contents.charAt(search) == "\t")){
669                        search--;
670                }
671               
672                if(search < idx -1){
673                        contents = contents.substring(0, search + 1)
674                                        + contents.substring(idx, contents.length);
675                       
676                        idx = contents.indexOf("\n", search + 2);
677                }else{
678                        idx = contents.indexOf("\n", idx + 1);
679                }
680        }
681
682        return contents;
683}
684
685checkstyleUtil.fixSpaceAfter = function(contents, token, comments){
686        var idx = contents.indexOf(token + " ");
687       
688        while(idx > -1){
689                if(!comments[idx]){
690                        contents = checkstyleUtil.deleteChar(contents, idx + token.length);
691                }
692               
693                idx = contents.indexOf(token + " ", idx + token.length);
694        }
695        return contents;
696}
697
698checkstyleUtil.fixSpaceBeforeAndAfter = function(contents, token, comments){
699        var idx = contents.indexOf(token);
700        var before, after;
701        var len = token.length;
702
703        while(idx > -1){
704                before = contents.charAt(idx - 1);
705                after = contents.charAt(idx + len);
706                if(!comments[idx]){
707                        // Only insert a space before the token if:
708                        // - char before is not a space or a tab
709                        // - token is "==" and the char before is neither "!" or "="
710               
711                        if(before != " " && before != "\t"
712                                && (token != "==" || (before != "!" && before != "="))
713                                && (token != "=" ||
714                                                (before != "<" &&
715                                                 before != ">" &&
716                                                 before != "=" &&
717                                                 before != "!" &&
718                                                 before != "+" &&
719                                                 before != "-" &&
720                                                 before != "*" &&
721                                                 before != "/" &&
722                                                 before != "&" &&
723                                                 before != "|" ))
724                                ){
725                               
726                                contents = checkstyleUtil.insertChar(contents, " ", idx);
727                                idx ++;
728                        }
729                       
730                        // Only insert a space after the token if:
731                        // - char after is not a space
732                        // - char after is not a new line
733                        // - char after is not "="
734                        if((after != " " && contents.charCodeAt(idx + len) != 13
735                                        && contents.charCodeAt(idx + len) != 10)
736                                        && (token != "==" || after != "=")
737                                        && (token != "!=" || after != "=")
738                                        && (token != "=" || after != "=")
739                                        && (token != "<" || after != "=")
740                                        && (token != ">" || after != "=")
741                                        && (token != "&" || after != "=")
742                                        && (token != "|" || after != "=")
743                                        && (token != "+" || after != "=")
744                                        && (token != "-" || after != "=")
745                                        && (token != "*" || after != "=")
746                                        && (token != "/" || after != "=")
747                                       
748                                        ){
749                                contents = contents = checkstyleUtil.insertChar(contents, " ", idx + token.length);
750                                idx++;
751                        }
752                }
753                idx = contents.indexOf(token, idx + token.length);
754        }
755        return contents;
756}
757
758// Creates the data file suitable to be loaded into a dojo.data.ItemFileReadStore
759checkstyleUtil.generateReport = function(skipPrint){
760       
761        var ids = 1;
762        var json = ["{id:'" +(ids++) + "', file: 'All', isFolder:true}"];
763
764        // A map of folders that have already been found.
765        var allFolders = {};
766       
767        var messageIds = {};
768        var messageCounter = 1;
769        var i, err;
770       
771        function getFolderName(fileName){
772                // Extract the folder name from a file name
773                var idx = fileName.lastIndexOf("/");
774                return fileName.substring(0, idx);
775        }
776       
777        // Add a folder to the list of folders.
778        function pushFolder(folderName){
779                if(!allFolders[folderName]){
780                        allFolders[folderName] = true;
781                        json.push("{id: '" +(ids++) + "', file: '" + folderName + "', folder: 1}");
782                }
783        }
784       
785        for(i = 0; i < checkstyleUtil.errors.length; i++){
786                err = checkstyleUtil.errors[i];
787                var message = err.message;
788                var messageId = messageIds[message];
789                if(!messageId){
790                        messageId = "m" + messageCounter++;
791                        messageIds[message] = messageId;
792                       
793                        json.push("{id:'" + messageId +
794                                        "',msg:'" + message +
795                                        "'}");
796                }
797        }
798       
799        pushFolder("All");
800       
801        // Create the JSON records for each error.
802        for(i = 0; i < checkstyleUtil.errors.length; i++){
803                err = checkstyleUtil.errors[i];
804                var folderName = getFolderName(err.file);
805                pushFolder(folderName);
806               
807                json.push("{id:'" +(ids++) +
808                                        "', file:'" + err.file +
809                                        "',line:" + err.line +
810                                        ",msg:{'_reference':'" + messageIds[err.message] +
811                                        //"'},folder:'" + folderName +
812                                        "'},folder: 0" +
813                                        "}");
814               
815        }
816
817        // Add the date that the check was run to the store.
818        json.push("{id:'" +(ids++) + "', date: " +(new Date()).getTime() + "}");
819       
820        // Save the file.
821
822        if(!skipPrint){
823                print("Found " + checkstyleUtil.errors.length + " checkstyle errors. " +
824                "Open the file checkstyleReport.html to view the results.");
825        }
826                                       
827        return "{ identifier: 'id', label:'file', items: [" + json.join(",\n") + "]}";
828};
Note: See TracBrowser for help on using the repository browser.