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]));