Commit a22cc40b authored by vitalyp@chromium.org's avatar vitalyp@chromium.org

Add ChromeCodingConvention.java to Closure Compiler to preserve getInstance() type

BUG=393873
R=dbeam@chromium.org
TEST=python2 third_party/closure_compiler/coding_conventions_test.py

Review URL: https://codereview.chromium.org/421253006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287727 0039d316-1c4b-4281-b951-d872f2087c98
parent ae3d1b7b
......@@ -19,7 +19,7 @@ class LineNumber(object):
class FileCache(object):
_cache = defaultdict(str)
def _read(self, file):
file = os.path.abspath(file)
self._cache[file] = self._cache[file] or open(file, "r").read()
......@@ -128,10 +128,9 @@ class Checker(object):
if self._verbose:
print "(INFO) " + msg
def _fatal(self, msg):
print >> sys.stderr, "(FATAL) " + msg
def _error(self, msg):
print >> sys.stderr, "(ERROR) " + msg
self._clean_up()
sys.exit(1)
def _run_command(self, cmd):
cmd_str = " ".join(cmd)
......@@ -142,15 +141,15 @@ class Checker(object):
cmd_str, stdout=devnull, stderr=subprocess.PIPE, shell=True)
def _check_java_path(self):
if self._found_java:
return
if not self._found_java:
proc = self._run_command(["which", "java"])
proc.communicate()
if proc.returncode == 0:
self._found_java = True
else:
self._error("Cannot find java (`which java` => %s)" % proc.returncode)
proc = self._run_command(["which", "java"])
proc.communicate()
if proc.returncode == 0:
self._found_java = True
else:
self._fatal("Cannot find java (`which java` => %s)" % proc.returncode)
return self._found_java
def _run_jar(self, jar, args=[]):
self._check_java_path()
......@@ -181,6 +180,9 @@ class Checker(object):
return tmp_file.name
def check(self, file, depends=[], externs=[]):
if not self._check_java_path():
return 1, ""
self._debug("FILE: " + file)
if file.endswith("_externs.js"):
......@@ -216,10 +218,10 @@ class Checker(object):
output = self._format_errors(map(self._fix_up_error, errors))
if runner_cmd.returncode:
self._fatal("Error in: " + file + ("\n" + output if output else ""))
self._error("Error in: " + file + ("\n" + output if output else ""))
elif output:
self._debug("Output: " + output)
self._clean_up()
return runner_cmd.returncode == 0
return runner_cmd.returncode, output
#!/usr/bin/env python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import unittest
from checker import Checker, FileCache
class CodingConventionTest(unittest.TestCase):
def setUp(self):
self._checker = Checker(verbose=False)
def testGetInstance(self):
file_content = """
var cr = {
/** @param {!Function} ctor */
addSingletonGetter: function(ctor) {
ctor.getInstance = function() {
return ctor.instance_ || (ctor.instance_ = new ctor());
};
}
};
/** @constructor */
function Class() {
/** @param {number} num */
this.needsNumber = function(num) {};
}
cr.addSingletonGetter(Class);
Class.getInstance().needsNumber("wrong type");
"""
expected_chunk = "ERROR - actual parameter 1 of Class.needsNumber does not match formal parameter"
file_path = "/script.js"
FileCache._cache[file_path] = file_content
_, output = self._checker.check(file_path)
self.assertTrue(expected_chunk in output,
msg="%s\n\nExpected chunk: \n%s\n\nOutput:\n%s\n" % (
"getInstance", expected_chunk, output))
if __name__ == "__main__":
unittest.main()
......@@ -6,6 +6,8 @@
import argparse
from checker import Checker as Checker
import os
import sys
try:
import json
except:
......@@ -45,7 +47,7 @@ class ModuleParser(object):
def parse(self, file_path):
if file_path in self._cache:
print "(INFO) Found module file %s in the cache" % file_path
print "(INFO) Found module file %s in the cache" % file_path
return self._cache[file_path]
file = open(file_path, "r")
......@@ -97,7 +99,10 @@ class ModuleCompiler(object):
for s in m.sources:
depends = [rel_path(d) for d in m.depends]
externs = [rel_path(e) for e in m.externs]
self._checker.check(rel_path(s), depends=depends, externs=externs)
exit_code, _ = self._checker.check(rel_path(s), depends=depends,
externs=externs)
if exit_code:
sys.exit(exit_code)
if s != m.sources[-1]:
self._debug(os.linesep, prefix="")
......
......@@ -27,6 +27,7 @@ src_path = rel_to_abs(src_dir)
def run_and_communicate(command, error_template):
print >> sys.stderr, command
proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
proc.communicate()
if proc.returncode:
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.closure.compiler;
import com.google.javascript.jscomp.CodingConvention;
import com.google.javascript.jscomp.CodingConventions;
import com.google.javascript.jscomp.DiagnosticType;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.jstype.FunctionType;
import com.google.javascript.rhino.jstype.ObjectType;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class ChromeCodingConvention extends CodingConventions.Proxy {
private final Set<String> indirectlyDeclaredProperties;
public ChromeCodingConvention() {
this(CodingConventions.getDefault());
}
public ChromeCodingConvention(CodingConvention wrapped) {
super(wrapped);
Set<String> props = Sets.newHashSet("instance_", "getInstance");
props.addAll(wrapped.getIndirectlyDeclaredProperties());
indirectlyDeclaredProperties = ImmutableSet.copyOf(props);
}
@Override
public String getSingletonGetterClassName(Node callNode) {
Node callArg = callNode.getFirstChild();
if (!(callArg.matchesQualifiedName("cr.addSingletonGetter")) ||
callNode.getChildCount() != 2) {
return super.getSingletonGetterClassName(callNode);
}
return callArg.getNext().getQualifiedName();
}
@Override
public void applySingletonGetter(FunctionType functionType,
FunctionType getterType, ObjectType objectType) {
super.applySingletonGetter(functionType, getterType, objectType);
functionType.defineDeclaredProperty("getInstance", getterType,
functionType.getSource());
functionType.defineDeclaredProperty("instance_", objectType,
functionType.getSource());
}
@Override
public Collection<String> getIndirectlyDeclaredProperties() {
return indirectlyDeclaredProperties;
}
}
......@@ -12,6 +12,8 @@ import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.chromium.closure.compiler.ChromeCodingConvention;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
......@@ -189,6 +191,13 @@ public class Runner {
return options;
}
@Override
protected void setRunOptions(CompilerOptions options)
throws FlagUsageException, IOException {
super.setRunOptions(options);
options.setCodingConvention(new ChromeCodingConvention());
}
int execute() {
int result = 0;
int runs = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment