1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 // Simple Java identifier name pattern checker. You can check 33 // class, method and variable names in java sources to confirm 34 // to specified patterns. Default check functions just check for 35 // 'too short' names. You can customize checkXYZName functions to 36 // have arbitrary name pattern checks. 37 38 // Usage: jjs checknames.js -- <directory> 39 40 if (arguments.length == 0) { 41 print("Usage: jjs checknames.js -- <directory>"); 42 exit(1); 43 } 44 45 // Java types used 46 var File = Java.type("java.io.File"); 47 var Files = Java.type("java.nio.file.Files"); 48 var StringArray = Java.type("java.lang.String[]"); 49 var ToolProvider = Java.type("javax.tools.ToolProvider"); 50 var Tree = Java.type("com.sun.source.tree.Tree"); 51 var Trees = Java.type("com.sun.source.util.Trees"); 52 var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); 53 54 // replace these checkXYZ functions with checks you want! 55 function checkClassName(name) { 56 return name.length < 3; 57 } 58 59 function checkMethodName(name) { 60 return name.length < 3; 61 } 62 63 function checkVarName(name) { 64 return name.length < 3; 65 } 66 67 function checkNames() { 68 // get the system compiler tool 69 var compiler = ToolProvider.systemJavaCompiler; 70 // get standard file manager 71 var fileMgr = compiler.getStandardFileManager(null, null, null); 72 // Using Java.to convert script array (arguments) to a Java String[] 73 var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray)); 74 // create a new compilation task 75 var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); 76 var sourcePositions = Trees.instance(task).sourcePositions; 77 // subclass SimpleTreeVisitor 78 var NameChecker = Java.extend(TreeScanner); 79 80 var visitor = new NameChecker() { 81 report: function(node) { 82 var pos = sourcePositions.getStartPosition(this.compUnit, node); 83 var line = this.lineMap.getLineNumber(pos); 84 var col = this.lineMap.getColumnNumber(pos); 85 print("Too short name: " + node.name + " @ " + this.fileName + ":" + line + ":" + col); 86 }, 87 88 // override to capture information on current compilation unit 89 visitCompilationUnit: function(compUnit, p) { 90 this.compUnit = compUnit; 91 this.lineMap = compUnit.lineMap; 92 this.fileName = compUnit.sourceFile.name; 93 94 return Java.super(visitor).visitCompilationUnit(compUnit, p); 95 }, 96 97 // override to check class name 98 visitClass: function(node, p) { 99 if (checkClassName(node.simpleName.toString())) { 100 this.report(node); 101 } 102 103 return Java.super(visitor).visitClass(node, p); 104 }, 105 106 // override to check method name 107 visitMethod: function(node, p) { 108 if (checkMethodName(node.name.toString())) { 109 this.report(node); 110 } 111 112 return Java.super(visitor).visitMethod(node, p); 113 }, 114 115 // override to check variable name 116 visitVariable: function(node, p) { 117 if (checkVarName(node.name.toString())) { 118 this.report(node); 119 } 120 121 return Java.super(visitor).visitVariable(node, p); 122 } 123 } 124 125 for each (var cu in task.parse()) { 126 cu.accept(visitor, null); 127 } 128 } 129 130 // for each ".java" file in directory (recursively). 131 function main(dir) { 132 var totalCount = 0; 133 Files.walk(dir.toPath()). 134 forEach(function(p) { 135 var name = p.toFile().absolutePath; 136 if (name.endsWith(".java")) { 137 checkNames(p); 138 } 139 }); 140 } 141 142 main(new File(arguments[0]));