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

Side by Side Diff: third_party/closure_linter/closure_linter/typeannotation_test.py

Issue 2592193002: Remove closure_linter from Chrome (Closed)
Patch Set: Created 3 years, 12 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
(Empty)
1 #!/usr/bin/env python
2 """Unit tests for the typeannotation module."""
3
4
5
6
7 import unittest as googletest
8
9 from closure_linter import testutil
10 from closure_linter.common import erroraccumulator
11
12 CRAZY_TYPE = ('Array.<!function(new:X,{a:null},...(c|d)):'
13 'function(...(Object.<string>))>')
14
15
16 class TypeErrorException(Exception):
17 """Exception for TypeErrors."""
18
19 def __init__(self, errors):
20 super(TypeErrorException, self).__init__()
21 self.errors = errors
22
23
24 class TypeParserTest(googletest.TestCase):
25 """Tests for typeannotation parsing."""
26
27 def _ParseComment(self, script):
28 """Parse a script that contains one comment and return it."""
29 accumulator = erroraccumulator.ErrorAccumulator()
30 _, comments = testutil.ParseFunctionsAndComments(script, accumulator)
31 if accumulator.GetErrors():
32 raise TypeErrorException(accumulator.GetErrors())
33 self.assertEquals(1, len(comments))
34 return comments[0]
35
36 def _ParseType(self, type_str):
37 """Creates a comment to parse and returns the parsed type."""
38 comment = self._ParseComment('/** @type {%s} **/' % type_str)
39 return comment.GetDocFlags()[0].jstype
40
41 def assertProperReconstruction(self, type_str, matching_str=None):
42 """Parses the type and asserts the its repr matches the type.
43
44 If matching_str is specified, it will assert that the repr matches this
45 string instead.
46
47 Args:
48 type_str: The type string to parse.
49 matching_str: A string the __repr__ of the parsed type should match.
50 Returns:
51 The parsed js_type.
52 """
53 parsed_type = self._ParseType(type_str)
54 # Use listEqual assertion to more easily identify the difference
55 self.assertListEqual(list(matching_str or type_str),
56 list(repr(parsed_type)))
57 self.assertEquals(matching_str or type_str, repr(parsed_type))
58
59 # Newlines will be inserted by the file writer.
60 self.assertEquals(type_str.replace('\n', ''), parsed_type.ToString())
61 return parsed_type
62
63 def assertNullable(self, type_str, nullable=True):
64 parsed_type = self.assertProperReconstruction(type_str)
65 self.assertEquals(nullable, parsed_type.GetNullability(),
66 '"%s" should %sbe nullable' %
67 (type_str, 'not ' if nullable else ''))
68
69 def assertNotNullable(self, type_str):
70 return self.assertNullable(type_str, nullable=False)
71
72 def testReconstruction(self):
73 self.assertProperReconstruction('*')
74 self.assertProperReconstruction('number')
75 self.assertProperReconstruction('(((number)))')
76 self.assertProperReconstruction('!number')
77 self.assertProperReconstruction('?!number')
78 self.assertProperReconstruction('number=')
79 self.assertProperReconstruction('number=!?', '?!number=')
80 self.assertProperReconstruction('number|?string')
81 self.assertProperReconstruction('(number|string)')
82 self.assertProperReconstruction('?(number|string)')
83 self.assertProperReconstruction('Object.<number,string>')
84 self.assertProperReconstruction('function(new:Object)')
85 self.assertProperReconstruction('function(new:Object):number')
86 self.assertProperReconstruction('function(new:Object,Element):number')
87 self.assertProperReconstruction('function(this:T,...)')
88 self.assertProperReconstruction('{a:?number}')
89 self.assertProperReconstruction('{a:?number,b:(number|string)}')
90 self.assertProperReconstruction('{c:{nested_element:*}|undefined}')
91 self.assertProperReconstruction('{handleEvent:function(?):?}')
92 self.assertProperReconstruction('function():?|null')
93 self.assertProperReconstruction('null|function():?|bar')
94
95 def testOptargs(self):
96 self.assertProperReconstruction('number=')
97 self.assertProperReconstruction('number|string=')
98 self.assertProperReconstruction('(number|string)=')
99 self.assertProperReconstruction('(number|string=)')
100 self.assertProperReconstruction('(number=|string)')
101 self.assertProperReconstruction('function(...):number=')
102
103 def testIndepth(self):
104 # Do an deeper check of the crazy identifier
105 crazy = self.assertProperReconstruction(CRAZY_TYPE)
106 self.assertEquals('Array.', crazy.identifier)
107 self.assertEquals(1, len(crazy.sub_types))
108 func1 = crazy.sub_types[0]
109 func2 = func1.return_type
110 self.assertEquals('function', func1.identifier)
111 self.assertEquals('function', func2.identifier)
112 self.assertEquals(3, len(func1.sub_types))
113 self.assertEquals(1, len(func2.sub_types))
114 self.assertEquals('Object.', func2.sub_types[0].sub_types[0].identifier)
115
116 def testIterIdentifiers(self):
117 nested_identifiers = self._ParseType('(a|{b:(c|function(new:d):e)})')
118 for identifier in ('a', 'b', 'c', 'd', 'e'):
119 self.assertIn(identifier, nested_identifiers.IterIdentifiers())
120
121 def testIsEmpty(self):
122 self.assertTrue(self._ParseType('').IsEmpty())
123 self.assertFalse(self._ParseType('?').IsEmpty())
124 self.assertFalse(self._ParseType('!').IsEmpty())
125 self.assertFalse(self._ParseType('<?>').IsEmpty())
126
127 def testIsConstructor(self):
128 self.assertFalse(self._ParseType('').IsConstructor())
129 self.assertFalse(self._ParseType('Array.<number>').IsConstructor())
130 self.assertTrue(self._ParseType('function(new:T)').IsConstructor())
131
132 def testIsVarArgsType(self):
133 self.assertTrue(self._ParseType('...number').IsVarArgsType())
134 self.assertTrue(self._ParseType('...Object|Array').IsVarArgsType())
135 self.assertTrue(self._ParseType('...(Object|Array)').IsVarArgsType())
136 self.assertFalse(self._ParseType('Object|...Array').IsVarArgsType())
137 self.assertFalse(self._ParseType('(...Object|Array)').IsVarArgsType())
138
139 def testIsUnknownType(self):
140 self.assertTrue(self._ParseType('?').IsUnknownType())
141 self.assertTrue(self._ParseType('Foo.<?>').sub_types[0].IsUnknownType())
142 self.assertFalse(self._ParseType('?|!').IsUnknownType())
143 self.assertTrue(self._ParseType('?|!').sub_types[0].IsUnknownType())
144 self.assertFalse(self._ParseType('!').IsUnknownType())
145
146 long_type = 'function():?|{handleEvent:function(?=):?,sample:?}|?='
147 record = self._ParseType(long_type)
148 # First check that there's not just one type with 3 return types, but three
149 # top-level types.
150 self.assertEquals(3, len(record.sub_types))
151
152 # Now extract all unknown type instances and verify that they really are.
153 handle_event, sample = record.sub_types[1].sub_types
154 for i, sub_type in enumerate([
155 record.sub_types[0].return_type,
156 handle_event.return_type,
157 handle_event.sub_types[0],
158 sample,
159 record.sub_types[2]]):
160 self.assertTrue(sub_type.IsUnknownType(),
161 'Type %d should be the unknown type: %s\n%s' % (
162 i, sub_type.tokens, record.Dump()))
163
164 def testTypedefNames(self):
165 easy = self._ParseType('{a}')
166 self.assertTrue(easy.record_type)
167
168 easy = self.assertProperReconstruction('{a}', '{a:}').sub_types[0]
169 self.assertEquals('a', easy.key_type.identifier)
170 self.assertEquals('', easy.identifier)
171
172 easy = self.assertProperReconstruction('{a:b}').sub_types[0]
173 self.assertEquals('a', easy.key_type.identifier)
174 self.assertEquals('b', easy.identifier)
175
176 def assertTypeError(self, type_str):
177 """Asserts that parsing the given type raises a linter error."""
178 self.assertRaises(TypeErrorException, self._ParseType, type_str)
179
180 def testParseBadTypes(self):
181 """Tests that several errors in types don't break the parser."""
182 self.assertTypeError('<')
183 self.assertTypeError('>')
184 self.assertTypeError('Foo.<Bar')
185 self.assertTypeError('Foo.Bar>=')
186 self.assertTypeError('Foo.<Bar>>=')
187 self.assertTypeError('(')
188 self.assertTypeError(')')
189 self.assertTypeError('Foo.<Bar)>')
190 self._ParseType(':')
191 self._ParseType(':foo')
192 self.assertTypeError(':)foo')
193 self.assertTypeError('(a|{b:(c|function(new:d):e')
194
195 def testNullable(self):
196 self.assertNullable('null')
197 self.assertNullable('Object')
198 self.assertNullable('?string')
199 self.assertNullable('?number')
200
201 self.assertNotNullable('string')
202 self.assertNotNullable('number')
203 self.assertNotNullable('boolean')
204 self.assertNotNullable('function(Object)')
205 self.assertNotNullable('function(Object):Object')
206 self.assertNotNullable('function(?Object):?Object')
207 self.assertNotNullable('!Object')
208
209 self.assertNotNullable('boolean|string')
210 self.assertNotNullable('(boolean|string)')
211
212 self.assertNullable('(boolean|string|null)')
213 self.assertNullable('(?boolean)')
214 self.assertNullable('?(boolean)')
215
216 self.assertNullable('(boolean|Object)')
217 self.assertNotNullable('(boolean|(string|{a:}))')
218
219 def testSpaces(self):
220 """Tests that spaces don't change the outcome."""
221 type_str = (' A < b | ( c | ? ! d e f ) > | '
222 'function ( x : . . . ) : { y : z = } ')
223 two_spaces = type_str.replace(' ', ' ')
224 no_spaces = type_str.replace(' ', '')
225 newlines = type_str.replace(' ', '\n * ')
226 self.assertProperReconstruction(no_spaces)
227 self.assertProperReconstruction(type_str, no_spaces)
228 self.assertProperReconstruction(two_spaces, no_spaces)
229 self.assertProperReconstruction(newlines, no_spaces)
230
231 if __name__ == '__main__':
232 googletest.main()
233
OLDNEW
« no previous file with comments | « third_party/closure_linter/closure_linter/typeannotation.py ('k') | third_party/closure_linter/setup.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698