| Index: third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py
|
| diff --git a/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py b/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py
|
| index 42499419efadab27309076e59ecf98fa7cf07722..7aeae21956af8d27d005ec9fe22567ac951548d2 100755
|
| --- a/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py
|
| +++ b/third_party/closure_linter/closure_linter/closurizednamespacesinfo_test.py
|
| @@ -31,6 +31,11 @@ from closure_linter import tokenutil
|
| TokenType = javascripttokens.JavaScriptTokenType
|
|
|
|
|
| +def _ToLineDict(illegal_alias_stmts):
|
| + """Replaces tokens with the respective line number."""
|
| + return {k: v.line_number for k, v in illegal_alias_stmts.iteritems()}
|
| +
|
| +
|
| class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| """Tests for ClosurizedNamespacesInfo."""
|
|
|
| @@ -123,6 +128,16 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| self.assertTrue(namespaces_info.IsExtraProvide(token),
|
| 'Should be extra since it is not created.')
|
|
|
| + def testIsExtraProvide_notCreatedMultipartClosurizedNamespace(self):
|
| + """Tests that provides for non-created namespaces are extra."""
|
| + input_lines = ['goog.provide(\'multi.part.namespace.Foo\');']
|
| +
|
| + token, namespaces_info = self._GetStartTokenAndNamespacesInfoForScript(
|
| + input_lines, ['multi.part'])
|
| +
|
| + self.assertTrue(namespaces_info.IsExtraProvide(token),
|
| + 'Should be extra since it is not created.')
|
| +
|
| def testIsExtraProvide_duplicate(self):
|
| """Tests that providing a namespace twice makes the second one extra."""
|
| input_lines = [
|
| @@ -186,6 +201,17 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| self.assertTrue(namespaces_info.IsExtraRequire(token),
|
| 'Should be extra since it is not used.')
|
|
|
| + def testIsExtraRequire_notUsedMultiPartClosurizedNamespace(self):
|
| + """Tests unused require with multi-part closurized namespaces."""
|
| +
|
| + input_lines = ['goog.require(\'multi.part.namespace.Foo\');']
|
| +
|
| + token, namespaces_info = self._GetStartTokenAndNamespacesInfoForScript(
|
| + input_lines, ['multi.part'])
|
| +
|
| + self.assertTrue(namespaces_info.IsExtraRequire(token),
|
| + 'Should be extra since it is not used.')
|
| +
|
| def testIsExtraRequire_notClosurized(self):
|
| """Tests that requires of non-closurized namespaces are not extra."""
|
| input_lines = ['goog.require(\'notclosurized.Foo\');']
|
| @@ -329,7 +355,8 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| - self.assertEquals(0, len(namespaces_info.GetMissingProvides()))
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(0, len(missing_requires))
|
|
|
| def testGetMissingRequires_requiredIdentifier(self):
|
| """Tests that required namespaces satisfy identifiers on that namespace."""
|
| @@ -339,7 +366,19 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| - self.assertEquals(0, len(namespaces_info.GetMissingProvides()))
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(0, len(missing_requires))
|
| +
|
| + def testGetMissingRequires_requiredNamespace(self):
|
| + """Tests that required namespaces satisfy the namespace."""
|
| + input_lines = [
|
| + 'goog.require(\'package.soy.fooTemplate\');',
|
| + 'render(package.soy.fooTemplate);'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(0, len(missing_requires))
|
|
|
| def testGetMissingRequires_requiredParentClass(self):
|
| """Tests that requiring a parent class of an object is sufficient to prevent
|
| @@ -351,7 +390,8 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| - self.assertEquals(0, len(namespaces_info.GetMissingRequires()))
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(0, len(missing_requires))
|
|
|
| def testGetMissingRequires_unrequired(self):
|
| """Tests that unrequired namespaces cause a missing require."""
|
| @@ -359,7 +399,7 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
|
|
| - missing_requires = namespaces_info.GetMissingRequires()
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| self.assertEquals(1, len(missing_requires))
|
| missing_req = missing_requires.popitem()
|
| self.assertEquals('package.Foo', missing_req[0])
|
| @@ -373,7 +413,8 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| - self.assertEquals(0, len(namespaces_info.GetMissingRequires()))
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(0, len(missing_requires))
|
|
|
| def testGetMissingRequires_created(self):
|
| """Tests that created namespaces do not satisfy usage of an identifier."""
|
| @@ -386,7 +427,7 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
|
|
| - missing_requires = namespaces_info.GetMissingRequires()
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| self.assertEquals(1, len(missing_requires))
|
| missing_require = missing_requires.popitem()
|
| self.assertEquals('package.Foo', missing_require[0])
|
| @@ -401,7 +442,19 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| - self.assertEquals(0, len(namespaces_info.GetMissingRequires()))
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(0, len(missing_requires))
|
| +
|
| + def testGetMissingRequires_implements(self):
|
| + """Tests that a parametrized type requires the correct identifier."""
|
| + input_lines = [
|
| + '/** @constructor @implements {package.Bar<T>} */',
|
| + 'package.Foo = function();',
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertItemsEqual({'package.Bar': 1}, missing_requires)
|
|
|
| def testGetMissingRequires_objectOnClass(self):
|
| """Tests that we should require a class, not the object on the class."""
|
| @@ -411,7 +464,8 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['package'])
|
| - self.assertEquals(1, len(namespaces_info.GetMissingRequires()),
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals(1, len(missing_requires),
|
| 'The whole class, not the object, should be required.')
|
|
|
| def testGetMissingRequires_variableWithSameName(self):
|
| @@ -447,7 +501,7 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| 'docs',
|
| 'lvalue',
|
| 'dummy'])
|
| - missing_requires = namespaces_info.GetMissingRequires()
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| self.assertEquals(2, len(missing_requires))
|
| self.assertItemsEqual(
|
| {'dummy.xyz': 14,
|
| @@ -491,7 +545,7 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| self.assertTrue(namespaces_info._scopified_file)
|
|
|
| def testScope_unusedAlias(self):
|
| - """Tests that an used alias symbol doesn't result in a require."""
|
| + """Tests that an unused alias symbol is illegal."""
|
| input_lines = [
|
| 'goog.scope(function() {',
|
| 'var Event = goog.events.Event;',
|
| @@ -499,8 +553,24 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| - missing_requires = namespaces_info.GetMissingRequires()
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| self.assertEquals({}, missing_requires)
|
| + self.assertEquals({'goog.events': 2}, _ToLineDict(illegal_alias_stmts))
|
| +
|
| + def testScope_usedMultilevelAlias(self):
|
| + """Tests that an used alias symbol in a deep namespace is ok."""
|
| + input_lines = [
|
| + 'goog.require(\'goog.Events\');',
|
| + 'goog.scope(function() {',
|
| + 'var Event = goog.Events.DeepNamespace.Event;',
|
| + 'Event();',
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({}, illegal_alias_stmts)
|
|
|
| def testScope_usedAlias(self):
|
| """Tests that aliased symbols result in correct requires."""
|
| @@ -513,10 +583,207 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ]
|
|
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| - missing_requires = namespaces_info.GetMissingRequires()
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, illegal_alias_stmts)
|
| self.assertEquals({'goog.dom.classes': 4, 'goog.events.Event': 4},
|
| missing_requires)
|
|
|
| + def testModule_alias(self):
|
| + """Tests that goog.module style aliases are supported."""
|
| + input_lines = [
|
| + 'goog.module(\'test.module\');',
|
| + 'var Unused = goog.require(\'goog.Unused\');',
|
| + 'var AliasedClass = goog.require(\'goog.AliasedClass\');',
|
| + 'var x = new AliasedClass();',
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + namespaceToken = self._GetRequireTokens('goog.AliasedClass')
|
| + self.assertFalse(namespaces_info.IsExtraRequire(namespaceToken),
|
| + 'AliasedClass should be marked as used')
|
| + unusedToken = self._GetRequireTokens('goog.Unused')
|
| + self.assertTrue(namespaces_info.IsExtraRequire(unusedToken),
|
| + 'Unused should be marked as not used')
|
| +
|
| + def testModule_aliasInScope(self):
|
| + """Tests that goog.module style aliases are supported."""
|
| + input_lines = [
|
| + 'goog.module(\'test.module\');',
|
| + 'var AliasedClass = goog.require(\'goog.AliasedClass\');',
|
| + 'goog.scope(function() {',
|
| + 'var x = new AliasedClass();',
|
| + '});',
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + namespaceToken = self._GetRequireTokens('goog.AliasedClass')
|
| + self.assertFalse(namespaces_info.IsExtraRequire(namespaceToken),
|
| + 'AliasedClass should be marked as used')
|
| +
|
| + def testModule_getAlwaysProvided(self):
|
| + """Tests that goog.module.get is recognized as a built-in."""
|
| + input_lines = [
|
| + 'goog.provide(\'test.MyClass\');',
|
| + 'goog.require(\'goog.someModule\');',
|
| + 'goog.scope(function() {',
|
| + 'var someModule = goog.module.get(\'goog.someModule\');',
|
| + 'test.MyClass = function() {};',
|
| + '});',
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + self.assertEquals({}, namespaces_info.GetMissingRequires()[0])
|
| +
|
| + def testModule_requireForGet(self):
|
| + """Tests that goog.module.get needs a goog.require call."""
|
| + input_lines = [
|
| + 'goog.provide(\'test.MyClass\');',
|
| + 'function foo() {',
|
| + ' var someModule = goog.module.get(\'goog.someModule\');',
|
| + ' someModule.doSth();',
|
| + '}',
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + self.assertEquals({'goog.someModule': 3},
|
| + namespaces_info.GetMissingRequires()[0])
|
| +
|
| + def testScope_usedTypeAlias(self):
|
| + """Tests aliased symbols in type annotations."""
|
| + input_lines = [
|
| + 'goog.scope(function() {',
|
| + 'var Event = goog.events.Event;',
|
| + '/** @type {Event} */;',
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({'goog.events': 2}, _ToLineDict(illegal_alias_stmts))
|
| +
|
| + def testScope_partialAlias_typeOnly(self):
|
| + """Tests a partial alias only used in type annotations.
|
| +
|
| + In this example, some goog.events namespace would need to be required
|
| + so that evaluating goog.events.bar doesn't throw an error.
|
| + """
|
| + input_lines = [
|
| + 'goog.scope(function() {',
|
| + 'var bar = goog.events.bar;',
|
| + '/** @type {bar.Foo} */;',
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({'goog.events': 2}, _ToLineDict(illegal_alias_stmts))
|
| +
|
| + def testScope_partialAlias(self):
|
| + """Tests a partial alias in conjunction with a type annotation.
|
| +
|
| + In this example, the partial alias is already defined by another type,
|
| + therefore the doc-only type doesn't need to be required.
|
| + """
|
| + input_lines = [
|
| + 'goog.scope(function() {',
|
| + 'var bar = goog.events.bar;',
|
| + '/** @type {bar.Event} */;',
|
| + 'bar.EventType();'
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({'goog.events.bar.EventType': 4}, missing_requires)
|
| + self.assertEquals({}, illegal_alias_stmts)
|
| +
|
| + def testScope_partialAliasRequires(self):
|
| + """Tests partial aliases with correct requires."""
|
| + input_lines = [
|
| + 'goog.require(\'goog.events.bar.EventType\');',
|
| + 'goog.scope(function() {',
|
| + 'var bar = goog.events.bar;',
|
| + '/** @type {bar.Event} */;',
|
| + 'bar.EventType();'
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({}, illegal_alias_stmts)
|
| +
|
| + def testScope_partialAliasRequiresBoth(self):
|
| + """Tests partial aliases with correct requires."""
|
| + input_lines = [
|
| + 'goog.require(\'goog.events.bar.Event\');',
|
| + 'goog.require(\'goog.events.bar.EventType\');',
|
| + 'goog.scope(function() {',
|
| + 'var bar = goog.events.bar;',
|
| + '/** @type {bar.Event} */;',
|
| + 'bar.EventType();'
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({}, illegal_alias_stmts)
|
| + event_token = self._GetRequireTokens('goog.events.bar.Event')
|
| + self.assertTrue(namespaces_info.IsExtraRequire(event_token))
|
| +
|
| + def testScope_partialAliasNoSubtypeRequires(self):
|
| + """Tests that partial aliases don't yield subtype requires (regression)."""
|
| + input_lines = [
|
| + 'goog.provide(\'goog.events.Foo\');',
|
| + 'goog.scope(function() {',
|
| + 'goog.events.Foo = {};',
|
| + 'var Foo = goog.events.Foo;'
|
| + 'Foo.CssName_ = {};'
|
| + 'var CssName_ = Foo.CssName_;'
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, _ = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| +
|
| + def testScope_aliasNamespace(self):
|
| + """Tests that an unused alias namespace is not required when available.
|
| +
|
| + In the example goog.events.Bar is not required, because the namespace
|
| + goog.events is already defined because goog.events.Foo is required.
|
| + """
|
| + input_lines = [
|
| + 'goog.require(\'goog.events.Foo\');',
|
| + 'goog.scope(function() {',
|
| + 'var Bar = goog.events.Bar;',
|
| + '/** @type {Bar} */;',
|
| + 'goog.events.Foo;',
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({}, illegal_alias_stmts)
|
| +
|
| + def testScope_aliasNamespaceIllegal(self):
|
| + """Tests that an unused alias namespace is not required when available."""
|
| + input_lines = [
|
| + 'goog.scope(function() {',
|
| + 'var Bar = goog.events.Bar;',
|
| + '/** @type {Bar} */;',
|
| + '});'
|
| + ]
|
| +
|
| + namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| + missing_requires, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, missing_requires)
|
| + self.assertEquals({'goog.events': 2}, _ToLineDict(illegal_alias_stmts))
|
| +
|
| def testScope_provides(self):
|
| """Tests that aliased symbols result in correct provides."""
|
| input_lines = [
|
| @@ -530,6 +797,8 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| namespaces_info = self._GetNamespacesInfoForScript(input_lines, ['goog'])
|
| missing_provides = namespaces_info.GetMissingProvides()
|
| self.assertEquals({'goog.bar.Foo': 4}, missing_provides)
|
| + _, illegal_alias_stmts = namespaces_info.GetMissingRequires()
|
| + self.assertEquals({}, illegal_alias_stmts)
|
|
|
| def testSetTestOnlyNamespaces(self):
|
| """Tests that a namespace in setTestOnly makes it a valid provide."""
|
| @@ -577,6 +846,8 @@ class ClosurizedNamespacesInfoTest(googletest.TestCase):
|
| ecma_pass = ecmametadatapass.EcmaMetaDataPass()
|
| ecma_pass.Process(token)
|
|
|
| + state_tracker.DocFlagPass(token, error_handler=None)
|
| +
|
| alias_pass = aliaspass.AliasPass(closurized_namespaces)
|
| alias_pass.Process(token)
|
|
|
|
|