Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: third_party/closure_compiler/runner/src/com/google/javascript/jscomp/ChromePass.java

Issue 557633002: Add public API generation with cr.makePublic() and handle it in compiler pass (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@H_options_errors_3
Patch Set: manually handle exported methods declared in base class Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package com.google.javascript.jscomp; 5 package com.google.javascript.jscomp;
6 6
7 import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; 7 import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
8 import com.google.javascript.rhino.IR; 8 import com.google.javascript.rhino.IR;
9 import com.google.javascript.rhino.JSDocInfoBuilder; 9 import com.google.javascript.rhino.JSDocInfoBuilder;
10 import com.google.javascript.rhino.JSTypeExpression; 10 import com.google.javascript.rhino.JSTypeExpression;
(...skipping 19 matching lines...) Expand all
30 */ 30 */
31 public class ChromePass extends AbstractPostOrderCallback implements CompilerPas s { 31 public class ChromePass extends AbstractPostOrderCallback implements CompilerPas s {
32 final AbstractCompiler compiler; 32 final AbstractCompiler compiler;
33 33
34 private Set<String> createdObjects; 34 private Set<String> createdObjects;
35 35
36 private static final String CR_DEFINE = "cr.define"; 36 private static final String CR_DEFINE = "cr.define";
37 private static final String CR_EXPORT_PATH = "cr.exportPath"; 37 private static final String CR_EXPORT_PATH = "cr.exportPath";
38 private static final String OBJECT_DEFINE_PROPERTY = "Object.defineProperty" ; 38 private static final String OBJECT_DEFINE_PROPERTY = "Object.defineProperty" ;
39 private static final String CR_DEFINE_PROPERTY = "cr.defineProperty"; 39 private static final String CR_DEFINE_PROPERTY = "cr.defineProperty";
40 private static final String CR_MAKE_PUBLIC = "cr.makePublic";
40 41
41 private static final String CR_DEFINE_COMMON_EXPLANATION = "It should be cal led like this:" 42 private static final String CR_DEFINE_COMMON_EXPLANATION = "It should be cal led like this:"
42 + " cr.define('name.space', function() '{ ... return {Export: Intern al}; }');"; 43 + " cr.define('name.space', function() '{ ... return {Export: Intern al}; }');";
43 44
44 static final DiagnosticType CR_DEFINE_WRONG_NUMBER_OF_ARGUMENTS = 45 static final DiagnosticType CR_DEFINE_WRONG_NUMBER_OF_ARGUMENTS =
45 DiagnosticType.error("JSC_CR_DEFINE_WRONG_NUMBER_OF_ARGUMENTS", 46 DiagnosticType.error("JSC_CR_DEFINE_WRONG_NUMBER_OF_ARGUMENTS",
46 "cr.define() should have exactly 2 arguments. " + CR_DEFINE_ COMMON_EXPLANATION); 47 "cr.define() should have exactly 2 arguments. " + CR_DEFINE_ COMMON_EXPLANATION);
47 48
48 static final DiagnosticType CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS = 49 static final DiagnosticType CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS =
49 DiagnosticType.error("JSC_CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS", 50 DiagnosticType.error("JSC_CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS",
(...skipping 10 matching lines...) Expand all
60 static final DiagnosticType CR_DEFINE_INVALID_RETURN_IN_FUNCTION = 61 static final DiagnosticType CR_DEFINE_INVALID_RETURN_IN_FUNCTION =
61 DiagnosticType.error("JSC_CR_DEFINE_INVALID_RETURN_IN_SECOND_ARGUMEN T", 62 DiagnosticType.error("JSC_CR_DEFINE_INVALID_RETURN_IN_SECOND_ARGUMEN T",
62 "Function passed as second argument of cr.define() should re turn the" 63 "Function passed as second argument of cr.define() should re turn the"
63 + " dictionary in its last statement. " + CR_DEFINE_COMMON_E XPLANATION); 64 + " dictionary in its last statement. " + CR_DEFINE_COMMON_E XPLANATION);
64 65
65 static final DiagnosticType CR_DEFINE_PROPERTY_INVALID_PROPERTY_KIND = 66 static final DiagnosticType CR_DEFINE_PROPERTY_INVALID_PROPERTY_KIND =
66 DiagnosticType.error("JSC_CR_DEFINE_PROPERTY_INVALID_PROPERTY_KIND", 67 DiagnosticType.error("JSC_CR_DEFINE_PROPERTY_INVALID_PROPERTY_KIND",
67 "Invalid cr.PropertyKind passed to cr.defineProperty(): expe cted ATTR," 68 "Invalid cr.PropertyKind passed to cr.defineProperty(): expe cted ATTR,"
68 + " BOOL_ATTR or JS, found \"{0}\"."); 69 + " BOOL_ATTR or JS, found \"{0}\".");
69 70
71 static final DiagnosticType CR_MAKE_PUBLIC_HAS_NO_JSDOC =
72 DiagnosticType.error("JSC_CR_MAKE_PUBLIC_HAS_NO_JSDOC",
73 "Private method exported by cr.makePublic() has no JSDoc.");
74
75 static final DiagnosticType CR_MAKE_PUBLIC_MISSED_DECLARATION =
76 DiagnosticType.error("JSC_CR_MAKE_PUBLIC_MISSED_DECLARATION",
77 "Method \"{1}_\" exported by cr.makePublic() on \"{0}\" has no declaration.");
78
79 static final DiagnosticType CR_MAKE_PUBLIC_INVALID_SECOND_ARGUMENT =
80 DiagnosticType.error("JSC_CR_MAKE_PUBLIC_INVALID_SECOND_ARGUMENT",
81 "Invalid second argument passed to cr.makePublic(): should b e array of " +
82 "strings.");
83
70 public ChromePass(AbstractCompiler compiler) { 84 public ChromePass(AbstractCompiler compiler) {
71 this.compiler = compiler; 85 this.compiler = compiler;
72 // The global variable "cr" is declared in ui/webui/resources/js/cr.js. 86 // The global variable "cr" is declared in ui/webui/resources/js/cr.js.
73 this.createdObjects = new HashSet<>(Arrays.asList("cr")); 87 this.createdObjects = new HashSet<>(Arrays.asList("cr"));
74 } 88 }
75 89
76 @Override 90 @Override
77 public void process(Node externs, Node root) { 91 public void process(Node externs, Node root) {
78 NodeTraversal.traverse(compiler, root, this); 92 NodeTraversal.traverse(compiler, root, this);
79 } 93 }
80 94
81 @Override 95 @Override
82 public void visit(NodeTraversal t, Node node, Node parent) { 96 public void visit(NodeTraversal t, Node node, Node parent) {
83 if (node.isCall()) { 97 if (node.isCall()) {
84 Node callee = node.getFirstChild(); 98 Node callee = node.getFirstChild();
85 if (callee.matchesQualifiedName(CR_DEFINE)) { 99 if (callee.matchesQualifiedName(CR_DEFINE)) {
86 visitNamespaceDefinition(node, parent); 100 visitNamespaceDefinition(node, parent);
87 compiler.reportCodeChange(); 101 compiler.reportCodeChange();
88 } else if (callee.matchesQualifiedName(CR_EXPORT_PATH)) { 102 } else if (callee.matchesQualifiedName(CR_EXPORT_PATH)) {
89 visitExportPath(node, parent); 103 visitExportPath(node, parent);
90 compiler.reportCodeChange(); 104 compiler.reportCodeChange();
91 } else if (callee.matchesQualifiedName(OBJECT_DEFINE_PROPERTY) || 105 } else if (callee.matchesQualifiedName(OBJECT_DEFINE_PROPERTY) ||
92 callee.matchesQualifiedName(CR_DEFINE_PROPERTY)) { 106 callee.matchesQualifiedName(CR_DEFINE_PROPERTY)) {
93 visitPropertyDefinition(node, parent); 107 visitPropertyDefinition(node, parent);
94 compiler.reportCodeChange(); 108 compiler.reportCodeChange();
109 } else if (callee.matchesQualifiedName(CR_MAKE_PUBLIC)) {
110 if (visitMakePublic(node, parent)) {
111 compiler.reportCodeChange();
112 }
95 } 113 }
96 } 114 }
97 } 115 }
98 116
99 private void visitPropertyDefinition(Node call, Node parent) { 117 private void visitPropertyDefinition(Node call, Node parent) {
100 Node callee = call.getFirstChild(); 118 Node callee = call.getFirstChild();
101 String target = call.getChildAtIndex(1).getQualifiedName(); 119 String target = call.getChildAtIndex(1).getQualifiedName();
102 if (callee.matchesQualifiedName(CR_DEFINE_PROPERTY) && !target.endsWith( ".prototype")) { 120 if (callee.matchesQualifiedName(CR_DEFINE_PROPERTY) && !target.endsWith( ".prototype")) {
103 target += ".prototype"; 121 target += ".prototype";
104 } 122 }
(...skipping 28 matching lines...) Expand all
133 propertyKind.getQualifiedName())); 151 propertyKind.getQualifiedName()));
134 return null; 152 return null;
135 } 153 }
136 154
137 private void setJsDocWithType(Node target, Node type) { 155 private void setJsDocWithType(Node target, Node type) {
138 JSDocInfoBuilder builder = new JSDocInfoBuilder(false); 156 JSDocInfoBuilder builder = new JSDocInfoBuilder(false);
139 builder.recordType(new JSTypeExpression(type, "")); 157 builder.recordType(new JSTypeExpression(type, ""));
140 target.setJSDocInfo(builder.build(target)); 158 target.setJSDocInfo(builder.build(target));
141 } 159 }
142 160
161 private boolean visitMakePublic(Node call, Node exprResult) {
162 boolean changesMade = false;
163 Node scope = exprResult.getParent();
164 String className = call.getChildAtIndex(1).getQualifiedName();
165 String prototype = className + ".prototype";
166 Node publicAPI = call.getChildAtIndex(2);
Dan Beam 2014/09/10 19:26:27 methods
Vitaly Pavlenko 2014/09/10 20:25:21 Done.
167
168 if (publicAPI == null || !publicAPI.isArrayLit()) {
169 compiler.report(JSError.make(exprResult, CR_MAKE_PUBLIC_INVALID_SECO ND_ARGUMENT));
170 return changesMade;
171 }
172
173 Set<String> publicAPIStrings = new HashSet<>();
Dan Beam 2014/09/10 19:26:27 methodNames
Vitaly Pavlenko 2014/09/10 20:25:21 Done.
174 for (Node methodName: publicAPI.children()) {
175 if (!methodName.isString()) {
176 compiler.report(JSError.make(methodName, CR_MAKE_PUBLIC_INVALID_ SECOND_ARGUMENT));
177 return changesMade;
178 }
179 publicAPIStrings.add(methodName.getString());
180 }
181
182 for (Node child: scope.children()) {
183 if (isAssignmentToPrototype(child, prototype)) {
184 Node objectLit = child.getFirstChild().getChildAtIndex(1);
185 for (Node stringKey : objectLit.children()) {
186 String field = stringKey.getString();
187 changesMade |= maybeAddPublicDeclaration(field, publicAPIStr ings, className,
188 stringKey, scope, e xprResult);
189 }
190 } else if (isAssignmentToPrototypeMethod(child, prototype)) {
191 Node assignNode = child.getFirstChild();
192 String qualifiedName = assignNode.getFirstChild().getQualifiedNa me();
193 String field = qualifiedName.substring(qualifiedName.lastIndexOf ('.') + 1);
194 changesMade |= maybeAddPublicDeclaration(field, publicAPIStrings , className,
195 assignNode, scope, expr Result);
196 } else if (isDummyPrototypeMethodDeclaration(child, prototype)) {
197 String qualifiedName = child.getFirstChild().getQualifiedName();
198 String field = qualifiedName.substring(qualifiedName.lastIndexOf ('.') + 1);
199 changesMade |= maybeAddPublicDeclaration(field, publicAPIStrings , className,
200 child.getFirstChild(), scope, exprResult);
201 }
202 }
203
204 for (String missedDeclaration : publicAPIStrings) {
205 compiler.report(JSError.make(exprResult, CR_MAKE_PUBLIC_MISSED_DECLA RATION, className,
206 missedDeclaration));
207 }
208
209 return changesMade;
210 }
211
212 private boolean isAssignmentToPrototype(Node node, String prototype) {
213 Node assignNode;
214 return node.isExprResult() && (assignNode = node.getFirstChild()).isAssi gn() &&
215 assignNode.getFirstChild().getQualifiedName().equals(prototype);
216 }
217
218 private boolean isAssignmentToPrototypeMethod(Node node, String prototype) {
219 Node assignNode;
220 return node.isExprResult() && (assignNode = node.getFirstChild()).isAssi gn() &&
221 assignNode.getFirstChild().getQualifiedName().startsWith(prototy pe + ".");
222 }
223
224 private boolean isDummyPrototypeMethodDeclaration(Node node, String prototyp e) {
225 Node getPropNode;
226 return node.isExprResult() && (getPropNode = node.getFirstChild()).isGet Prop() &&
227 getPropNode.getQualifiedName().startsWith(prototype + ".");
228 }
229
230 private boolean maybeAddPublicDeclaration(String field, Set<String> publicAP IStrings,
231 String className, Node jsDocSourceNode, Node scope, Node exprResult) {
232 boolean changesMade = false;
233 if (field.endsWith("_")) {
234 String publicName = field.substring(0, field.length() - 1);
235 if (publicAPIStrings.contains(publicName)) {
236 Node methodDeclaration = NodeUtil.newQualifiedNameNode(
237 compiler.getCodingConvention(), className + "." + public Name);
238 if (jsDocSourceNode.getJSDocInfo() != null) {
239 methodDeclaration.setJSDocInfo(jsDocSourceNode.getJSDocInfo( ));
240 scope.addChildBefore(
241 IR.exprResult(methodDeclaration).srcrefTree(exprResu lt),
242 exprResult);
243 changesMade = true;
244 } else {
245 compiler.report(JSError.make(jsDocSourceNode, CR_MAKE_PUBLIC _HAS_NO_JSDOC));
246 }
247 publicAPIStrings.remove(publicName);
248 }
249 }
250 return changesMade;
251 }
252
143 private void visitExportPath(Node crExportPathNode, Node parent) { 253 private void visitExportPath(Node crExportPathNode, Node parent) {
144 if (crExportPathNode.getChildCount() != 2) { 254 if (crExportPathNode.getChildCount() != 2) {
145 compiler.report(JSError.make(crExportPathNode, 255 compiler.report(JSError.make(crExportPathNode,
146 CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS)); 256 CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS));
147 return; 257 return;
148 } 258 }
149 259
150 createAndInsertObjectsForQualifiedName(parent, 260 createAndInsertObjectsForQualifiedName(parent,
151 crExportPathNode.getChildAtIndex(1).getString()); 261 crExportPathNode.getChildAtIndex(1).getString());
152 } 262 }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 } 445 }
336 } 446 }
337 } 447 }
338 448
339 private Node buildQualifiedName(Node internalName) { 449 private Node buildQualifiedName(Node internalName) {
340 String externalName = this.exports.get(internalName.getString()); 450 String externalName = this.exports.get(internalName.getString());
341 return NodeUtil.newQualifiedNameNode(compiler.getCodingConvention(), 451 return NodeUtil.newQualifiedNameNode(compiler.getCodingConvention(),
342 this.namespaceName + "." + externalName).srcrefTree(internal Name); 452 this.namespaceName + "." + externalName).srcrefTree(internal Name);
343 } 453 }
344 } 454 }
345
346 } 455 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698