clean up FeatureCheck signature to move location to use time

The point of a .use() function is because we don't always have the
information we need to use a feature check, so we allow creating the
feature and then storing it for later use. When implementing location
checks, although it is optional, actually using it violated that design.

Move the location out of the init method for FeatureCheck itself. It
remains compatible with all cases of .single_use(), but fix the rest up.
pull/10044/head
Eli Schwartz 3 years ago committed by Dylan Baker
parent 2b04e8c5e5
commit d39b330075
  1. 4
      mesonbuild/interpreter/interpreterobjects.py
  2. 24
      mesonbuild/interpreterbase/decorators.py
  3. 4
      mesonbuild/modules/unstable_external_project.py

@ -253,7 +253,7 @@ class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], Mutab
# Multiple append/prepend operations was not supported until 0.58.0. # Multiple append/prepend operations was not supported until 0.58.0.
if self.held_object.has_name(name): if self.held_object.has_name(name):
m = f'Overriding previous value of environment variable {name!r} with a new one' m = f'Overriding previous value of environment variable {name!r} with a new one'
FeatureNew(m, '0.58.0', location=self.current_node).use(self.subproject) FeatureNew(m, '0.58.0').use(self.subproject, self.current_node)
@typed_pos_args('environment.set', str, varargs=str, min_varargs=1) @typed_pos_args('environment.set', str, varargs=str, min_varargs=1)
@typed_kwargs('environment.set', ENV_SEPARATOR_KW) @typed_kwargs('environment.set', ENV_SEPARATOR_KW)
@ -480,7 +480,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> T.Union[str, T.List[str]]: def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> T.Union[str, T.List[str]]:
default_varname = args[0] default_varname = args[0]
if default_varname is not None: if default_varname is not None:
FeatureNew('Positional argument to dependency.get_variable()', '0.58.0', location=self.current_node).use(self.subproject) FeatureNew('Positional argument to dependency.get_variable()', '0.58.0').use(self.subproject, self.current_node)
return self.held_object.get_variable( return self.held_object.get_variable(
cmake=kwargs['cmake'] or default_varname, cmake=kwargs['cmake'] or default_varname,
pkgconfig=kwargs['pkgconfig'] or default_varname, pkgconfig=kwargs['pkgconfig'] or default_varname,

@ -583,11 +583,10 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
feature_registry: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional['mparser.BaseNode']]]]]] feature_registry: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional['mparser.BaseNode']]]]]]
emit_notice = False emit_notice = False
def __init__(self, feature_name: str, feature_version: str, extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None): def __init__(self, feature_name: str, feature_version: str, extra_message: str = ''):
self.feature_name = feature_name # type: str self.feature_name = feature_name # type: str
self.feature_version = feature_version # type: str self.feature_version = feature_version # type: str
self.extra_message = extra_message # type: str self.extra_message = extra_message # type: str
self.location = location
@staticmethod @staticmethod
def get_target_version(subproject: str) -> str: def get_target_version(subproject: str) -> str:
@ -601,7 +600,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
def check_version(target_version: str, feature_version: str) -> bool: def check_version(target_version: str, feature_version: str) -> bool:
pass pass
def use(self, subproject: 'SubProject') -> None: def use(self, subproject: 'SubProject', location: T.Optional['mparser.BaseNode'] = None) -> None:
tv = self.get_target_version(subproject) tv = self.get_target_version(subproject)
# No target version # No target version
if tv == '': if tv == '':
@ -616,7 +615,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
if self.feature_version not in register: if self.feature_version not in register:
register[self.feature_version] = set() register[self.feature_version] = set()
feature_key = (self.feature_name, self.location) feature_key = (self.feature_name, location)
if feature_key in register[self.feature_version]: if feature_key in register[self.feature_version]:
# Don't warn about the same feature multiple times # Don't warn about the same feature multiple times
# FIXME: This is needed to prevent duplicate warnings, but also # FIXME: This is needed to prevent duplicate warnings, but also
@ -626,7 +625,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
# Target version is new enough, don't warn even if it is registered for notice # Target version is new enough, don't warn even if it is registered for notice
if self.check_version(tv, self.feature_version): if self.check_version(tv, self.feature_version):
return return
self.log_usage_warning(tv) self.log_usage_warning(tv, location)
@classmethod @classmethod
def report(cls, subproject: str) -> None: def report(cls, subproject: str) -> None:
@ -646,7 +645,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
if '\n' in warning_str: if '\n' in warning_str:
mlog.warning(warning_str) mlog.warning(warning_str)
def log_usage_warning(self, tv: str) -> None: def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None:
raise InterpreterException('log_usage_warning not implemented') raise InterpreterException('log_usage_warning not implemented')
@staticmethod @staticmethod
@ -663,8 +662,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
node, _, _, subproject = get_callee_args(wrapped_args) node, _, _, subproject = get_callee_args(wrapped_args)
if subproject is None: if subproject is None:
raise AssertionError(f'{wrapped_args!r}') raise AssertionError(f'{wrapped_args!r}')
self.location = node self.use(subproject, node)
self.use(subproject)
return f(*wrapped_args, **wrapped_kwargs) return f(*wrapped_args, **wrapped_kwargs)
return T.cast(TV_func, wrapped) return T.cast(TV_func, wrapped)
@ -672,7 +670,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
def single_use(cls, feature_name: str, version: str, subproject: 'SubProject', def single_use(cls, feature_name: str, version: str, subproject: 'SubProject',
extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None) -> None: extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None) -> None:
"""Oneline version that instantiates and calls use().""" """Oneline version that instantiates and calls use()."""
cls(feature_name, version, extra_message, location).use(subproject) cls(feature_name, version, extra_message).use(subproject, location)
class FeatureNew(FeatureCheckBase): class FeatureNew(FeatureCheckBase):
@ -695,7 +693,7 @@ class FeatureNew(FeatureCheckBase):
def get_notice_str_prefix(tv: str) -> str: def get_notice_str_prefix(tv: str) -> str:
return '' return ''
def log_usage_warning(self, tv: str) -> None: def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None:
args = [ args = [
'Project targeting', f"'{tv}'", 'Project targeting', f"'{tv}'",
'but tried to use feature introduced in', 'but tried to use feature introduced in',
@ -704,7 +702,7 @@ class FeatureNew(FeatureCheckBase):
] ]
if self.extra_message: if self.extra_message:
args.append(self.extra_message) args.append(self.extra_message)
mlog.warning(*args, location=self.location) mlog.warning(*args, location=location)
class FeatureDeprecated(FeatureCheckBase): class FeatureDeprecated(FeatureCheckBase):
"""Checks for deprecated features""" """Checks for deprecated features"""
@ -728,7 +726,7 @@ class FeatureDeprecated(FeatureCheckBase):
def get_notice_str_prefix(tv: str) -> str: def get_notice_str_prefix(tv: str) -> str:
return 'Future-deprecated features used:' return 'Future-deprecated features used:'
def log_usage_warning(self, tv: str) -> None: def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None:
args = [ args = [
'Project targeting', f"'{tv}'", 'Project targeting', f"'{tv}'",
'but tried to use feature deprecated since', 'but tried to use feature deprecated since',
@ -737,7 +735,7 @@ class FeatureDeprecated(FeatureCheckBase):
] ]
if self.extra_message: if self.extra_message:
args.append(self.extra_message) args.append(self.extra_message)
mlog.warning(*args, location=self.location) mlog.warning(*args, location=location)
# This cannot be a dataclass due to https://github.com/python/mypy/issues/5374 # This cannot be a dataclass due to https://github.com/python/mypy/issues/5374

@ -101,7 +101,7 @@ class ExternalProject(NewExtensionModule):
def _configure(self, state: 'ModuleState') -> None: def _configure(self, state: 'ModuleState') -> None:
if self.configure_command == 'waf': if self.configure_command == 'waf':
FeatureNew('Waf external project', '0.60.0', location=state.current_node).use(self.subproject) FeatureNew('Waf external project', '0.60.0').use(self.subproject, state.current_node)
waf = state.find_program('waf') waf = state.find_program('waf')
configure_cmd = waf.get_command() configure_cmd = waf.get_command()
configure_cmd += ['configure', '-o', str(self.build_dir)] configure_cmd += ['configure', '-o', str(self.build_dir)]
@ -176,7 +176,7 @@ class ExternalProject(NewExtensionModule):
if key_format in option: if key_format in option:
break break
else: else:
FeatureNew('Default configure_option', '0.57.0', location=state.current_node).use(self.subproject) FeatureNew('Default configure_option', '0.57.0').use(self.subproject, state.current_node)
self.configure_options.append(default) self.configure_options.append(default)
def _format_options(self, options: T.List[str], variables: T.List[T.Tuple[str, str, str]]) -> T.List[str]: def _format_options(self, options: T.List[str], variables: T.List[T.Tuple[str, str, str]]) -> T.List[str]:

Loading…
Cancel
Save