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.
if self.held_object.has_name(name):
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_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]]:
default_varname = args[0]
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(
cmake=kwargs['cmake'] 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']]]]]]
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_version = feature_version # type: str
self.extra_message = extra_message # type: str
self.location = location
@staticmethod
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:
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)
# No target version
if tv == '':
@ -616,7 +615,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
if self.feature_version not in register:
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]:
# Don't warn about the same feature multiple times
# 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
if self.check_version(tv, self.feature_version):
return
self.log_usage_warning(tv)
self.log_usage_warning(tv, location)
@classmethod
def report(cls, subproject: str) -> None:
@ -646,7 +645,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
if '\n' in 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')
@staticmethod
@ -663,8 +662,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
node, _, _, subproject = get_callee_args(wrapped_args)
if subproject is None:
raise AssertionError(f'{wrapped_args!r}')
self.location = node
self.use(subproject)
self.use(subproject, node)
return f(*wrapped_args, **wrapped_kwargs)
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',
extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None) -> None:
"""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):
@ -695,7 +693,7 @@ class FeatureNew(FeatureCheckBase):
def get_notice_str_prefix(tv: str) -> str:
return ''
def log_usage_warning(self, tv: str) -> None:
def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None:
args = [
'Project targeting', f"'{tv}'",
'but tried to use feature introduced in',
@ -704,7 +702,7 @@ class FeatureNew(FeatureCheckBase):
]
if self.extra_message:
args.append(self.extra_message)
mlog.warning(*args, location=self.location)
mlog.warning(*args, location=location)
class FeatureDeprecated(FeatureCheckBase):
"""Checks for deprecated features"""
@ -728,7 +726,7 @@ class FeatureDeprecated(FeatureCheckBase):
def get_notice_str_prefix(tv: str) -> str:
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 = [
'Project targeting', f"'{tv}'",
'but tried to use feature deprecated since',
@ -737,7 +735,7 @@ class FeatureDeprecated(FeatureCheckBase):
]
if 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

@ -101,7 +101,7 @@ class ExternalProject(NewExtensionModule):
def _configure(self, state: 'ModuleState') -> None:
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')
configure_cmd = waf.get_command()
configure_cmd += ['configure', '-o', str(self.build_dir)]
@ -176,7 +176,7 @@ class ExternalProject(NewExtensionModule):
if key_format in option:
break
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)
def _format_options(self, options: T.List[str], variables: T.List[T.Tuple[str, str, str]]) -> T.List[str]:

Loading…
Cancel
Save