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

Unified Diff: third_party/closure_linter/closure_linter/typeannotation.py

Issue 2592193002: Remove closure_linter from Chrome (Closed)
Patch Set: Created 4 years 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 side-by-side diff with in-line comments
Download patch
Index: third_party/closure_linter/closure_linter/typeannotation.py
diff --git a/third_party/closure_linter/closure_linter/typeannotation.py b/third_party/closure_linter/closure_linter/typeannotation.py
deleted file mode 100644
index e8e270de241b968c5eabed5c1394499d21fe3400..0000000000000000000000000000000000000000
--- a/third_party/closure_linter/closure_linter/typeannotation.py
+++ /dev/null
@@ -1,410 +0,0 @@
-#!/usr/bin/env python
-#*-* coding: utf-8
-"""Closure typeannotation parsing and utilities."""
-
-
-
-from closure_linter import errors
-from closure_linter import javascripttokens
-from closure_linter.common import error
-
-# Shorthand
-TYPE = javascripttokens.JavaScriptTokenType
-
-
-class TypeAnnotation(object):
- """Represents a structured view of a closure type annotation.
-
- Attribute:
- identifier: The name of the type.
- key_type: The name part before a colon.
- sub_types: The list of sub_types used e.g. for Array.<…>
- or_null: The '?' annotation
- not_null: The '!' annotation
- type_group: If this a a grouping (a|b), but does not include function(a).
- return_type: The return type of a function definition.
- alias: The actual type set by closurizednamespaceinfo if the identifier uses
- an alias to shorten the name.
- tokens: An ordered list of tokens used for this type. May contain
- TypeAnnotation instances for sub_types, key_type or return_type.
- """
-
- IMPLICIT_TYPE_GROUP = 2
-
- NULLABILITY_UNKNOWN = 2
-
- FUNCTION_TYPE = 'function'
- NULL_TYPE = 'null'
- VAR_ARGS_TYPE = '...'
-
- # Frequently used known non-nullable types.
- NON_NULLABLE = frozenset([
- 'boolean', FUNCTION_TYPE, 'number', 'string', 'undefined'])
- # Frequently used known nullable types.
- NULLABLE_TYPE_WHITELIST = frozenset([
- 'Array', 'Document', 'Element', 'Function', 'Node', 'NodeList',
- 'Object'])
-
- def __init__(self):
- self.identifier = ''
- self.sub_types = []
- self.or_null = False
- self.not_null = False
- self.type_group = False
- self.alias = None
- self.key_type = None
- self.record_type = False
- self.opt_arg = False
- self.return_type = None
- self.tokens = []
-
- def IsFunction(self):
- """Determines whether this is a function definition."""
- return self.identifier == TypeAnnotation.FUNCTION_TYPE
-
- def IsConstructor(self):
- """Determines whether this is a function definition for a constructor."""
- key_type = self.sub_types and self.sub_types[0].key_type
- return self.IsFunction() and key_type.identifier == 'new'
-
- def IsRecordType(self):
- """Returns True if this type is a record type."""
- return (self.record_type or
- any(t.IsRecordType() for t in self.sub_types))
-
- def IsVarArgsType(self):
- """Determines if the type is a var_args type, i.e. starts with '...'."""
- return self.identifier.startswith(TypeAnnotation.VAR_ARGS_TYPE) or (
- self.type_group == TypeAnnotation.IMPLICIT_TYPE_GROUP and
- self.sub_types[0].identifier.startswith(TypeAnnotation.VAR_ARGS_TYPE))
-
- def IsEmpty(self):
- """Returns True if the type is empty."""
- return not self.tokens
-
- def IsUnknownType(self):
- """Returns True if this is the unknown type {?}."""
- return (self.or_null
- and not self.identifier
- and not self.sub_types
- and not self.return_type)
-
- def Append(self, item):
- """Adds a sub_type to this type and finalizes it.
-
- Args:
- item: The TypeAnnotation item to append.
- """
- # item is a TypeAnnotation instance, so pylint: disable=protected-access
- self.sub_types.append(item._Finalize(self))
-
- def __repr__(self):
- """Reconstructs the type definition."""
- append = ''
- if self.sub_types:
- separator = (',' if not self.type_group else '|')
- if self.IsFunction():
- surround = '(%s)'
- else:
- surround = {False: '{%s}' if self.record_type else '<%s>',
- True: '(%s)',
- TypeAnnotation.IMPLICIT_TYPE_GROUP: '%s'}[self.type_group]
- append = surround % separator.join(repr(t) for t in self.sub_types)
- if self.return_type:
- append += ':%s' % repr(self.return_type)
- append += '=' if self.opt_arg else ''
- prefix = '' + ('?' if self.or_null else '') + ('!' if self.not_null else '')
- keyword = '%s:' % repr(self.key_type) if self.key_type else ''
- return keyword + prefix + '%s' % (self.alias or self.identifier) + append
-
- def ToString(self):
- """Concats the type's tokens to form a string again."""
- ret = []
- for token in self.tokens:
- if not isinstance(token, TypeAnnotation):
- ret.append(token.string)
- else:
- ret.append(token.ToString())
- return ''.join(ret)
-
- def Dump(self, indent=''):
- """Dumps this type's structure for debugging purposes."""
- result = []
- for t in self.tokens:
- if isinstance(t, TypeAnnotation):
- result.append(indent + str(t) + ' =>\n' + t.Dump(indent + ' '))
- else:
- result.append(indent + str(t))
- return '\n'.join(result)
-
- def IterIdentifiers(self):
- """Iterates over all identifiers in this type and its subtypes."""
- if self.identifier:
- yield self.identifier
- for subtype in self.IterTypes():
- for identifier in subtype.IterIdentifiers():
- yield identifier
-
- def IterTypeGroup(self):
- """Iterates over all types in the type group including self.
-
- Yields:
- If this is a implicit or manual type-group: all sub_types.
- Otherwise: self
- E.g. for @type {Foo.<Bar>} this will yield only Foo.<Bar>,
- for @type {Foo|(Bar|Sample)} this will yield Foo, Bar and Sample.
-
- """
- if self.type_group:
- for sub_type in self.sub_types:
- for sub_type in sub_type.IterTypeGroup():
- yield sub_type
- else:
- yield self
-
- def IterTypes(self):
- """Iterates over each subtype as well as return and key types."""
- if self.return_type:
- yield self.return_type
-
- if self.key_type:
- yield self.key_type
-
- for sub_type in self.sub_types:
- yield sub_type
-
- def GetNullability(self, modifiers=True):
- """Computes whether the type may be null.
-
- Args:
- modifiers: Whether the modifiers ? and ! should be considered in the
- evaluation.
- Returns:
- True if the type allows null, False if the type is strictly non nullable
- and NULLABILITY_UNKNOWN if the nullability cannot be determined.
- """
-
- # Explicitly marked nullable types or 'null' are nullable.
- if ((modifiers and self.or_null) or
- self.identifier == TypeAnnotation.NULL_TYPE):
- return True
-
- # Explicitly marked non-nullable types or non-nullable base types:
- if ((modifiers and self.not_null) or self.record_type
- or self.identifier in TypeAnnotation.NON_NULLABLE):
- return False
-
- # A type group is nullable if any of its elements are nullable.
- if self.type_group:
- maybe_nullable = False
- for sub_type in self.sub_types:
- nullability = sub_type.GetNullability()
- if nullability == self.NULLABILITY_UNKNOWN:
- maybe_nullable = nullability
- elif nullability:
- return True
- return maybe_nullable
-
- # Whitelisted types are nullable.
- if self.identifier.rstrip('.') in TypeAnnotation.NULLABLE_TYPE_WHITELIST:
- return True
-
- # All other types are unknown (most should be nullable, but
- # enums are not and typedefs might not be).
- return TypeAnnotation.NULLABILITY_UNKNOWN
-
- def WillAlwaysBeNullable(self):
- """Computes whether the ! flag is illegal for this type.
-
- This is the case if this type or any of the subtypes is marked as
- explicitly nullable.
-
- Returns:
- True if the ! flag would be illegal.
- """
- if self.or_null or self.identifier == TypeAnnotation.NULL_TYPE:
- return True
-
- if self.type_group:
- return any(t.WillAlwaysBeNullable() for t in self.sub_types)
-
- return False
-
- def _Finalize(self, parent):
- """Fixes some parsing issues once the TypeAnnotation is complete."""
-
- # Normalize functions whose definition ended up in the key type because
- # they defined a return type after a colon.
- if (self.key_type and
- self.key_type.identifier == TypeAnnotation.FUNCTION_TYPE):
- current = self.key_type
- current.return_type = self
- self.key_type = None
- # opt_arg never refers to the return type but to the function itself.
- current.opt_arg = self.opt_arg
- self.opt_arg = False
- return current
-
- # If a typedef just specified the key, it will not end up in the key type.
- if parent.record_type and not self.key_type:
- current = TypeAnnotation()
- current.key_type = self
- current.tokens.append(self)
- return current
- return self
-
- def FirstToken(self):
- """Returns the first token used in this type or any of its subtypes."""
- first = self.tokens[0]
- return first.FirstToken() if isinstance(first, TypeAnnotation) else first
-
-
-def Parse(token, token_end, error_handler):
- """Parses a type annotation and returns a TypeAnnotation object."""
- return TypeAnnotationParser(error_handler).Parse(token.next, token_end)
-
-
-class TypeAnnotationParser(object):
- """A parser for type annotations constructing the TypeAnnotation object."""
-
- def __init__(self, error_handler):
- self._stack = []
- self._error_handler = error_handler
- self._closing_error = False
-
- def Parse(self, token, token_end):
- """Parses a type annotation and returns a TypeAnnotation object."""
- root = TypeAnnotation()
- self._stack.append(root)
- current = TypeAnnotation()
- root.tokens.append(current)
-
- while token and token != token_end:
- if token.type in (TYPE.DOC_TYPE_START_BLOCK, TYPE.DOC_START_BRACE):
- if token.string == '(':
- if current.identifier and current.identifier not in [
- TypeAnnotation.FUNCTION_TYPE, TypeAnnotation.VAR_ARGS_TYPE]:
- self.Error(token,
- 'Invalid identifier for (): "%s"' % current.identifier)
- current.type_group = (
- current.identifier != TypeAnnotation.FUNCTION_TYPE)
- elif token.string == '{':
- current.record_type = True
- current.tokens.append(token)
- self._stack.append(current)
- current = TypeAnnotation()
- self._stack[-1].tokens.append(current)
-
- elif token.type in (TYPE.DOC_TYPE_END_BLOCK, TYPE.DOC_END_BRACE):
- prev = self._stack.pop()
- prev.Append(current)
- current = prev
-
- # If an implicit type group was created, close it as well.
- if prev.type_group == TypeAnnotation.IMPLICIT_TYPE_GROUP:
- prev = self._stack.pop()
- prev.Append(current)
- current = prev
- current.tokens.append(token)
-
- elif token.type == TYPE.DOC_TYPE_MODIFIER:
- if token.string == '!':
- current.tokens.append(token)
- current.not_null = True
- elif token.string == '?':
- current.tokens.append(token)
- current.or_null = True
- elif token.string == ':':
- current.tokens.append(token)
- prev = current
- current = TypeAnnotation()
- prev.tokens.append(current)
- current.key_type = prev
- elif token.string == '=':
- # For implicit type groups the '=' refers to the parent.
- try:
- if self._stack[-1].type_group == TypeAnnotation.IMPLICIT_TYPE_GROUP:
- self._stack[-1].tokens.append(token)
- self._stack[-1].opt_arg = True
- else:
- current.tokens.append(token)
- current.opt_arg = True
- except IndexError:
- self.ClosingError(token)
- elif token.string == '|':
- # If a type group has explicitly been opened, do a normal append.
- # Otherwise we have to open the type group and move the current
- # type into it, before appending
- if not self._stack[-1].type_group:
- type_group = TypeAnnotation()
- if (current.key_type and
- current.key_type.identifier != TypeAnnotation.FUNCTION_TYPE):
- type_group.key_type = current.key_type
- current.key_type = None
- type_group.type_group = TypeAnnotation.IMPLICIT_TYPE_GROUP
- # Fix the token order
- prev = self._stack[-1].tokens.pop()
- self._stack[-1].tokens.append(type_group)
- type_group.tokens.append(prev)
- self._stack.append(type_group)
- self._stack[-1].tokens.append(token)
- self.Append(current, error_token=token)
- current = TypeAnnotation()
- self._stack[-1].tokens.append(current)
- elif token.string == ',':
- self.Append(current, error_token=token)
- current = TypeAnnotation()
- self._stack[-1].tokens.append(token)
- self._stack[-1].tokens.append(current)
- else:
- current.tokens.append(token)
- self.Error(token, 'Invalid token')
-
- elif token.type == TYPE.COMMENT:
- current.tokens.append(token)
- current.identifier += token.string.strip()
-
- elif token.type in [TYPE.DOC_PREFIX, TYPE.WHITESPACE]:
- current.tokens.append(token)
-
- else:
- current.tokens.append(token)
- self.Error(token, 'Unexpected token')
-
- token = token.next
-
- self.Append(current, error_token=token)
- try:
- ret = self._stack.pop()
- except IndexError:
- self.ClosingError(token)
- # The type is screwed up, but let's return something.
- return current
-
- if self._stack and (len(self._stack) != 1 or
- ret.type_group != TypeAnnotation.IMPLICIT_TYPE_GROUP):
- self.Error(token, 'Too many opening items.')
-
- return ret if len(ret.sub_types) > 1 else ret.sub_types[0]
-
- def Append(self, type_obj, error_token):
- """Appends a new TypeAnnotation object to the current parent."""
- if self._stack:
- self._stack[-1].Append(type_obj)
- else:
- self.ClosingError(error_token)
-
- def ClosingError(self, token):
- """Reports an error about too many closing items, but only once."""
- if not self._closing_error:
- self._closing_error = True
- self.Error(token, 'Too many closing items.')
-
- def Error(self, token, message):
- """Calls the error_handler to post an error message."""
- if self._error_handler:
- self._error_handler.HandleError(error.Error(
- errors.JSDOC_DOES_NOT_PARSE,
- 'Error parsing jsdoc type at token "%s" (column: %d): %s' %
- (token.string, token.start_index, message), token))
-

Powered by Google App Engine
This is Rietveld 408576698