Commit 68093821 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

IDL compiler: Add a validator (default value / constant)

Adds a validator that checks the type between literal values and
type of constants, arguments, and dictionary members.

Bug: 839389
Change-Id: I3bb9efd88508bedddba377531ef058b59a404739
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1920018
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#718074}
parent 1ad951f1
......@@ -44,3 +44,4 @@ web_idl/runtime_enabled_features.py
web_idl/typedef.py
web_idl/union.py
web_idl/user_defined_type.py
web_idl/validator.py
......@@ -54,3 +54,4 @@ web_idl/runtime_enabled_features.py
web_idl/typedef.py
web_idl/union.py
web_idl/user_defined_type.py
web_idl/validator.py
......@@ -77,3 +77,4 @@ web_idl/runtime_enabled_features.py
web_idl/typedef.py
web_idl/union.py
web_idl/user_defined_type.py
web_idl/validator.py
......@@ -24,6 +24,7 @@ from .typedef import Typedef
from .union import Union
from .user_defined_type import StubUserDefinedType
from .user_defined_type import UserDefinedType
from .validator import validate_after_resolve_references
class IdlCompiler(object):
......@@ -95,6 +96,7 @@ class IdlCompiler(object):
# Resolve references.
self._resolve_references_to_idl_def()
self._resolve_references_to_idl_type()
validate_after_resolve_references(self._ir_map)
# Build union API objects.
self._create_public_unions()
......
......@@ -274,6 +274,11 @@ class IdlType(WithExtendedAttributes, WithDebugInfo):
"""Returns True if this is an integer type."""
return False
@property
def is_floating_point_numeric(self):
"""Returns True if this is a floating point numeric type."""
return False
@property
def is_boolean(self):
"""Returns True if this is a boolean type."""
......@@ -500,8 +505,9 @@ class SimpleType(IdlType):
_INTEGER_TYPES = ('byte', 'octet', 'short', 'unsigned short', 'long',
'unsigned long', 'long long', 'unsigned long long')
_NUMERIC_TYPES = ('float', 'unrestricted float', 'double',
'unrestricted double') + _INTEGER_TYPES
_FLOATING_POINT_NUMERIC_TYPES = ('float', 'unrestricted float', 'double',
'unrestricted double')
_NUMERIC_TYPES = _FLOATING_POINT_NUMERIC_TYPES + _INTEGER_TYPES
_STRING_TYPES = ('DOMString', 'ByteString', 'USVString')
_VALID_TYPES = ('any', 'boolean', 'object', 'symbol',
'void') + _NUMERIC_TYPES + _STRING_TYPES
......@@ -552,6 +558,10 @@ class SimpleType(IdlType):
def is_integer(self):
return self._name in SimpleType._INTEGER_TYPES
@property
def is_floating_point_numeric(self):
return self._name in SimpleType._FLOATING_POINT_NUMERIC_TYPES
@property
def is_boolean(self):
return self._name == 'boolean'
......
......@@ -59,3 +59,35 @@ class LiteralConstant(object):
def literal(self):
"""Returns the literal representation."""
return self._literal
def is_type_compatible_with(self, idl_type):
"""Returns True if |idl_type| can store this value."""
assert isinstance(idl_type, IdlType)
idl_type = idl_type.unwrap(nullable=False)
if idl_type.is_any:
return True
if self.idl_type.is_nullable:
return idl_type.does_include_nullable_type
idl_type = idl_type.unwrap()
if idl_type.is_union:
return any(
self.is_type_compatible_with(member_type)
for member_type in idl_type.flattened_member_types)
if self.idl_type.is_sequence:
return idl_type.is_sequence
if self.idl_type.is_object:
return idl_type.is_dictionary
if self.idl_type.is_boolean:
return idl_type.is_boolean
if self.idl_type.is_integer:
return idl_type.is_numeric
if self.idl_type.is_floating_point_numeric:
return idl_type.is_floating_point_numeric
if self.idl_type.is_string:
return idl_type.is_string or idl_type.is_enumeration
# Copyright 2019 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.
from .ir_map import IRMap
def validate_after_resolve_references(ir_map):
_validate_literal_constant_type(ir_map)
def _all_constants(ir_map):
accumulated = []
irs = ir_map.irs_of_kinds(IRMap.IR.Kind.CALLBACK_INTERFACE,
IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.NAMESPACE)
for ir in irs:
accumulated.extend(ir.constants)
return accumulated
def _all_function_likes(ir_map):
accumulated = []
irs = ir_map.irs_of_kinds(IRMap.IR.Kind.CALLBACK_INTERFACE,
IRMap.IR.Kind.INTERFACE, IRMap.IR.Kind.NAMESPACE)
for ir in irs:
accumulated.extend(ir.constructors)
accumulated.extend(ir.operations)
accumulated.extend(ir_map.irs_of_kinds(IRMap.IR.Kind.CALLBACK_FUNCTION))
return accumulated
def _validate_literal_constant_type(ir_map):
for constant in _all_constants(ir_map):
assert constant.value.is_type_compatible_with(constant.idl_type), (
"{}: {}: The value is incompatible with the type.".format(
constant.debug_info.location, constant.identifier))
for function in _all_function_likes(ir_map):
for argument in function.arguments:
if argument.default_value is None:
continue
assert argument.default_value.is_type_compatible_with(
argument.idl_type
), ("{}: {}, {}: The default value is incompatible with the type.".
format(function.debug_info.location, function.identifier,
argument.identifier))
for dictionary in ir_map.irs_of_kind(IRMap.IR.Kind.DICTIONARY):
for dict_member in dictionary.own_members:
if dict_member.default_value is None:
continue
assert dict_member.default_value.is_type_compatible_with(
dict_member.idl_type
), ("{}: {}, {}: The default value is incompatible with the type.".
format(dict_member.debug_info.location, dictionary.identifier,
dict_member.identifier))
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