1"""Plugin system for extending mypy.
2
3At large scale the plugin system works as following:
4
5* Plugins are collected from the corresponding mypy config file option
6  (either via paths to Python files, or installed Python modules)
7  and imported using importlib.
8
9* Every module should get an entry point function (called 'plugin' by default,
10  but may be overridden in the config file) that should accept a single string
11  argument that is a full mypy version (includes git commit hash for dev
12  versions) and return a subclass of mypy.plugins.Plugin.
13
14* All plugin class constructors should match the signature of mypy.plugin.Plugin
15  (i.e. should accept an mypy.options.Options object), and *must* call
16  super().__init__().
17
18* At several steps during semantic analysis and type checking mypy calls
19  special `get_xxx` methods on user plugins with a single string argument that
20  is a fully qualified name (full name) of a relevant definition
21  (see mypy.plugin.Plugin method docstrings for details).
22
23* The plugins are called in the order they are passed in the config option.
24  Every plugin must decide whether to act on a given full name. The first
25  plugin that returns non-None object will be used.
26
27* The above decision should be made using the limited common API specified by
28  mypy.plugin.CommonPluginApi.
29
30* The callback returned by the plugin will be called with a larger context that
31  includes relevant current state (e.g. a default return type, or a default
32  attribute type) and a wider relevant API provider (e.g.
33  SemanticAnalyzerPluginInterface or CheckerPluginInterface).
34
35* The result of this is used for further processing. See various `XxxContext`
36  named tuples for details about which information is given to each hook.
37
38Plugin developers should ensure that their plugins work well in incremental and
39daemon modes. In particular, plugins should not hold global state, and should
40always call add_plugin_dependency() in plugin hooks called during semantic
41analysis. See the method docstring for more details.
42
43There is no dedicated cache storage for plugins, but plugins can store
44per-TypeInfo data in a special .metadata attribute that is serialized to the
45mypy caches between incremental runs. To avoid collisions between plugins, they
46are encouraged to store their state under a dedicated key coinciding with
47plugin name in the metadata dictionary. Every value stored there must be
48JSON-serializable.
49
50## Notes about the semantic analyzer
51
52Mypy 0.710 introduced a new semantic analyzer that changed how plugins are
53expected to work in several notable ways (from mypy 0.730 the old semantic
54analyzer is no longer available):
55
561. The order of processing AST nodes in modules is different. The old semantic
57   analyzer processed modules in textual order, one module at a time. The new
58   semantic analyzer first processes the module top levels, including bodies of
59   any top-level classes and classes nested within classes. ("Top-level" here
60   means "not nested within a function/method".) Functions and methods are
61   processed only after module top levels have been finished. If there is an
62   import cycle, all module top levels in the cycle are processed before
63   processing any functions or methods. Each unit of processing (a module top
64   level or a function/method) is called a *target*.
65
66   This also means that function signatures in the same module have not been
67   analyzed yet when analyzing the module top level. If you need access to
68   a function signature, you'll need to explicitly analyze the signature first
69   using `anal_type()`.
70
712. Each target can be processed multiple times. This may happen if some forward
72   references are not ready yet, for example. This means that semantic analyzer
73   related plugin hooks can be called multiple times for the same full name.
74   These plugin methods must thus be idempotent.
75
763. The `anal_type` API function returns None if some part of the type is not
77   available yet. If this happens, the current target being analyzed will be
78   *deferred*, which means that it will be processed again soon, in the hope
79   that additional dependencies will be available. This may happen if there are
80   forward references to types or inter-module references to types within an
81   import cycle.
82
83   Note that if there is a circular definition, mypy may decide to stop
84   processing to avoid an infinite number of iterations. When this happens,
85   `anal_type` will generate an error and return an `AnyType` type object
86   during the final iteration (instead of None).
87
884. There is a new API method `defer()`. This can be used to explicitly request
89   the current target to be reprocessed one more time. You don't need this
90   to call this if `anal_type` returns None, however.
91
925. There is a new API property `final_iteration`, which is true once mypy
93   detected no progress during the previous iteration or if the maximum
94   semantic analysis iteration count has been reached. You must never
95   defer during the final iteration, as it will cause a crash.
96
976. The `node` attribute of SymbolTableNode objects may contain a reference to
98   a PlaceholderNode object. This object means that this definition has not
99   been fully processed yet. If you encounter a PlaceholderNode, you should
100   defer unless it's the final iteration. If it's the final iteration, you
101   should generate an error message. It usually means that there's a cyclic
102   definition that cannot be resolved by mypy. PlaceholderNodes can only refer
103   to references inside an import cycle. If you are looking up things from
104   another module, such as the builtins, that is outside the current module or
105   import cycle, you can safely assume that you won't receive a placeholder.
106
107When testing your plugin, you should have a test case that forces a module top
108level to be processed multiple times. The easiest way to do this is to include
109a forward reference to a class in a top-level annotation. Example:
110
111    c: C  # Forward reference causes second analysis pass
112    class C: pass
113
114Note that a forward reference in a function signature won't trigger another
115pass, since all functions are processed only after the top level has been fully
116analyzed.
117
118You can use `api.options.new_semantic_analyzer` to check whether the new
119semantic analyzer is enabled (it's always true in mypy 0.730 and later).
120"""
121
122from abc import abstractmethod
123from typing import Any, Callable, List, Tuple, Optional, NamedTuple, TypeVar, Dict
124from mypy_extensions import trait, mypyc_attr
125
126from mypy.nodes import (
127    Expression, Context, ClassDef, SymbolTableNode, MypyFile, CallExpr
128)
129from mypy.tvar_scope import TypeVarLikeScope
130from mypy.types import Type, Instance, CallableType, TypeList, UnboundType, ProperType
131from mypy.messages import MessageBuilder
132from mypy.options import Options
133from mypy.lookup import lookup_fully_qualified
134from mypy.errorcodes import ErrorCode
135
136
137@trait
138class TypeAnalyzerPluginInterface:
139    """Interface for accessing semantic analyzer functionality in plugins.
140
141    Methods docstrings contain only basic info. Look for corresponding implementation
142    docstrings in typeanal.py for more details.
143    """
144
145    # An options object. Note: these are the cloned options for the current file.
146    # This might be different from Plugin.options (that contains default/global options)
147    # if there are per-file options in the config. This applies to all other interfaces
148    # in this file.
149    options = None  # type: Options
150
151    @abstractmethod
152    def fail(self, msg: str, ctx: Context, *, code: Optional[ErrorCode] = None) -> None:
153        """Emit an error message at given location."""
154        raise NotImplementedError
155
156    @abstractmethod
157    def named_type(self, name: str, args: List[Type]) -> Instance:
158        """Construct an instance of a builtin type with given name."""
159        raise NotImplementedError
160
161    @abstractmethod
162    def analyze_type(self, typ: Type) -> Type:
163        """Analyze an unbound type using the default mypy logic."""
164        raise NotImplementedError
165
166    @abstractmethod
167    def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type],
168                                                                         List[int],
169                                                                         List[Optional[str]]]]:
170        """Find types, kinds, and names of arguments from extended callable syntax."""
171        raise NotImplementedError
172
173
174# A context for a hook that semantically analyzes an unbound type.
175AnalyzeTypeContext = NamedTuple(
176    'AnalyzeTypeContext', [
177        ('type', UnboundType),  # Type to analyze
178        ('context', Context),   # Relevant location context (e.g. for error messages)
179        ('api', TypeAnalyzerPluginInterface)])
180
181
182@mypyc_attr(allow_interpreted_subclasses=True)
183class CommonPluginApi:
184    """
185    A common plugin API (shared between semantic analysis and type checking phases)
186    that all plugin hooks get independently of the context.
187    """
188
189    # Global mypy options.
190    # Per-file options can be only accessed on various
191    # XxxPluginInterface classes.
192    options = None  # type: Options
193
194    @abstractmethod
195    def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]:
196        """Lookup a symbol by its full name (including module).
197
198        This lookup function available for all plugins. Return None if a name
199        is not found. This function doesn't support lookup from current scope.
200        Use SemanticAnalyzerPluginInterface.lookup_qualified() for this."""
201        raise NotImplementedError
202
203
204@trait
205class CheckerPluginInterface:
206    """Interface for accessing type checker functionality in plugins.
207
208    Methods docstrings contain only basic info. Look for corresponding implementation
209    docstrings in checker.py for more details.
210    """
211
212    msg = None  # type: MessageBuilder
213    options = None  # type: Options
214    path = None  # type: str
215
216    # Type context for type inference
217    @property
218    @abstractmethod
219    def type_context(self) -> List[Optional[Type]]:
220        """Return the type context of the plugin"""
221        raise NotImplementedError
222
223    @abstractmethod
224    def fail(self, msg: str, ctx: Context, *, code: Optional[ErrorCode] = None) -> None:
225        """Emit an error message at given location."""
226        raise NotImplementedError
227
228    @abstractmethod
229    def named_generic_type(self, name: str, args: List[Type]) -> Instance:
230        """Construct an instance of a builtin type with given type arguments."""
231        raise NotImplementedError
232
233
234@trait
235class SemanticAnalyzerPluginInterface:
236    """Interface for accessing semantic analyzer functionality in plugins.
237
238    Methods docstrings contain only basic info. Look for corresponding implementation
239    docstrings in semanal.py for more details.
240
241    # TODO: clean-up lookup functions.
242    """
243
244    modules = None  # type: Dict[str, MypyFile]
245    # Options for current file.
246    options = None  # type: Options
247    cur_mod_id = None  # type: str
248    msg = None  # type: MessageBuilder
249
250    @abstractmethod
251    def named_type(self, qualified_name: str, args: Optional[List[Type]] = None) -> Instance:
252        """Construct an instance of a builtin type with given type arguments."""
253        raise NotImplementedError
254
255    @abstractmethod
256    def parse_bool(self, expr: Expression) -> Optional[bool]:
257        """Parse True/False literals."""
258        raise NotImplementedError
259
260    @abstractmethod
261    def fail(self, msg: str, ctx: Context, serious: bool = False, *,
262             blocker: bool = False, code: Optional[ErrorCode] = None) -> None:
263        """Emit an error message at given location."""
264        raise NotImplementedError
265
266    @abstractmethod
267    def anal_type(self, t: Type, *,
268                  tvar_scope: Optional[TypeVarLikeScope] = None,
269                  allow_tuple_literal: bool = False,
270                  allow_unbound_tvars: bool = False,
271                  report_invalid_types: bool = True,
272                  third_pass: bool = False) -> Optional[Type]:
273        """Analyze an unbound type.
274
275        Return None if some part of the type is not ready yet. In this
276        case the current target being analyzed will be deferred and
277        analyzed again.
278        """
279        raise NotImplementedError
280
281    @abstractmethod
282    def class_type(self, self_type: Type) -> Type:
283        """Generate type of first argument of class methods from type of self."""
284        raise NotImplementedError
285
286    @abstractmethod
287    def builtin_type(self, fully_qualified_name: str) -> Instance:
288        """Deprecated: use named_type instead."""
289        raise NotImplementedError
290
291    @abstractmethod
292    def lookup_fully_qualified(self, name: str) -> SymbolTableNode:
293        """Lookup a symbol by its fully qualified name.
294
295        Raise an error if not found.
296        """
297        raise NotImplementedError
298
299    @abstractmethod
300    def lookup_fully_qualified_or_none(self, name: str) -> Optional[SymbolTableNode]:
301        """Lookup a symbol by its fully qualified name.
302
303        Return None if not found.
304        """
305        raise NotImplementedError
306
307    @abstractmethod
308    def lookup_qualified(self, name: str, ctx: Context,
309                         suppress_errors: bool = False) -> Optional[SymbolTableNode]:
310        """Lookup symbol using a name in current scope.
311
312        This follows Python local->non-local->global->builtins rules.
313        """
314        raise NotImplementedError
315
316    @abstractmethod
317    def add_plugin_dependency(self, trigger: str, target: Optional[str] = None) -> None:
318        """Specify semantic dependencies for generated methods/variables.
319
320        If the symbol with full name given by trigger is found to be stale by mypy,
321        then the body of node with full name given by target will be re-checked.
322        By default, this is the node that is currently analyzed.
323
324        For example, the dataclass plugin adds a generated __init__ method with
325        a signature that depends on types of attributes in ancestor classes. If any
326        attribute in an ancestor class gets stale (modified), we need to reprocess
327        the subclasses (and thus regenerate __init__ methods).
328
329        This is used by fine-grained incremental mode (mypy daemon). See mypy/server/deps.py
330        for more details.
331        """
332        raise NotImplementedError
333
334    @abstractmethod
335    def add_symbol_table_node(self, name: str, stnode: SymbolTableNode) -> Any:
336        """Add node to global symbol table (or to nearest class if there is one)."""
337        raise NotImplementedError
338
339    @abstractmethod
340    def qualified_name(self, n: str) -> str:
341        """Make qualified name using current module and enclosing class (if any)."""
342        raise NotImplementedError
343
344    @abstractmethod
345    def defer(self) -> None:
346        """Call this to defer the processing of the current node.
347
348        This will request an additional iteration of semantic analysis.
349        """
350        raise NotImplementedError
351
352    @property
353    @abstractmethod
354    def final_iteration(self) -> bool:
355        """Is this the final iteration of semantic analysis?"""
356        raise NotImplementedError
357
358
359# A context for querying for configuration data about a module for
360# cache invalidation purposes.
361ReportConfigContext = NamedTuple(
362    'ReportConfigContext', [
363        ('id', str),        # Module name
364        ('path', str),      # Module file path
365        ('is_check', bool)  # Is this invocation for checking whether the config matches
366    ])
367
368# A context for a function signature hook that infers a better signature for a
369# function.  Note that argument types aren't available yet.  If you need them,
370# you have to use a method hook instead.
371FunctionSigContext = NamedTuple(
372    'FunctionSigContext', [
373        ('args', List[List[Expression]]),     # Actual expressions for each formal argument
374        ('default_signature', CallableType),  # Original signature of the method
375        ('context', Context),                 # Relevant location context (e.g. for error messages)
376        ('api', CheckerPluginInterface)])
377
378# A context for a function hook that infers the return type of a function with
379# a special signature.
380#
381# A no-op callback would just return the inferred return type, but a useful
382# callback at least sometimes can infer a more precise type.
383FunctionContext = NamedTuple(
384    'FunctionContext', [
385        ('arg_types', List[List[Type]]),   # List of actual caller types for each formal argument
386        ('arg_kinds', List[List[int]]),    # Ditto for argument kinds, see nodes.ARG_* constants
387        # Names of formal parameters from the callee definition,
388        # these will be sufficient in most cases.
389        ('callee_arg_names', List[Optional[str]]),
390        # Names of actual arguments in the call expression. For example,
391        # in a situation like this:
392        #     def func(**kwargs) -> None:
393        #         pass
394        #     func(kw1=1, kw2=2)
395        # callee_arg_names will be ['kwargs'] and arg_names will be [['kw1', 'kw2']].
396        ('arg_names', List[List[Optional[str]]]),
397        ('default_return_type', Type),     # Return type inferred from signature
398        ('args', List[List[Expression]]),  # Actual expressions for each formal argument
399        ('context', Context),              # Relevant location context (e.g. for error messages)
400        ('api', CheckerPluginInterface)])
401
402# A context for a method signature hook that infers a better signature for a
403# method.  Note that argument types aren't available yet.  If you need them,
404# you have to use a method hook instead.
405# TODO: document ProperType in the plugin changelog/update issue.
406MethodSigContext = NamedTuple(
407    'MethodSigContext', [
408        ('type', ProperType),                 # Base object type for method call
409        ('args', List[List[Expression]]),     # Actual expressions for each formal argument
410        ('default_signature', CallableType),  # Original signature of the method
411        ('context', Context),                 # Relevant location context (e.g. for error messages)
412        ('api', CheckerPluginInterface)])
413
414# A context for a method hook that infers the return type of a method with a
415# special signature.
416#
417# This is very similar to FunctionContext (only differences are documented).
418MethodContext = NamedTuple(
419    'MethodContext', [
420        ('type', ProperType),              # Base object type for method call
421        ('arg_types', List[List[Type]]),   # List of actual caller types for each formal argument
422        # see FunctionContext for details about names and kinds
423        ('arg_kinds', List[List[int]]),
424        ('callee_arg_names', List[Optional[str]]),
425        ('arg_names', List[List[Optional[str]]]),
426        ('default_return_type', Type),     # Return type inferred by mypy
427        ('args', List[List[Expression]]),  # Lists of actual expressions for every formal argument
428        ('context', Context),
429        ('api', CheckerPluginInterface)])
430
431# A context for an attribute type hook that infers the type of an attribute.
432AttributeContext = NamedTuple(
433    'AttributeContext', [
434        ('type', ProperType),         # Type of object with attribute
435        ('default_attr_type', Type),  # Original attribute type
436        ('context', Context),         # Relevant location context (e.g. for error messages)
437        ('api', CheckerPluginInterface)])
438
439# A context for a class hook that modifies the class definition.
440ClassDefContext = NamedTuple(
441    'ClassDefContext', [
442        ('cls', ClassDef),       # The class definition
443        ('reason', Expression),  # The expression being applied (decorator, metaclass, base class)
444        ('api', SemanticAnalyzerPluginInterface)
445    ])
446
447# A context for dynamic class definitions like
448# Base = declarative_base()
449DynamicClassDefContext = NamedTuple(
450    'DynamicClassDefContext', [
451        ('call', CallExpr),      # The r.h.s. of dynamic class definition
452        ('name', str),           # The name this class is being assigned to
453        ('api', SemanticAnalyzerPluginInterface)
454    ])
455
456
457@mypyc_attr(allow_interpreted_subclasses=True)
458class Plugin(CommonPluginApi):
459    """Base class of all type checker plugins.
460
461    This defines a no-op plugin.  Subclasses can override some methods to
462    provide some actual functionality.
463
464    All get_ methods are treated as pure functions (you should assume that
465    results might be cached). A plugin should return None from a get_ method
466    to give way to other plugins.
467
468    Look at the comments of various *Context objects for additional information on
469    various hooks.
470    """
471
472    def __init__(self, options: Options) -> None:
473        self.options = options
474        self.python_version = options.python_version
475        # This can't be set in __init__ because it is executed too soon in build.py.
476        # Therefore, build.py *must* set it later before graph processing starts
477        # by calling set_modules().
478        self._modules = None  # type: Optional[Dict[str, MypyFile]]
479
480    def set_modules(self, modules: Dict[str, MypyFile]) -> None:
481        self._modules = modules
482
483    def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]:
484        assert self._modules is not None
485        return lookup_fully_qualified(fullname, self._modules)
486
487    def report_config_data(self, ctx: ReportConfigContext) -> Any:
488        """Get representation of configuration data for a module.
489
490        The data must be encodable as JSON and will be stored in the
491        cache metadata for the module. A mismatch between the cached
492        values and the returned will result in that module's cache
493        being invalidated and the module being rechecked.
494
495        This can be called twice for each module, once after loading
496        the cache to check if it is valid and once while writing new
497        cache information.
498
499        If is_check in the context is true, then the return of this
500        call will be checked against the cached version. Otherwise the
501        call is being made to determine what to put in the cache. This
502        can be used to allow consulting extra cache files in certain
503        complex situations.
504
505        This can be used to incorporate external configuration information
506        that might require changes to typechecking.
507        """
508        return None
509
510    def get_additional_deps(self, file: MypyFile) -> List[Tuple[int, str, int]]:
511        """Customize dependencies for a module.
512
513        This hook allows adding in new dependencies for a module. It
514        is called after parsing a file but before analysis. This can
515        be useful if a library has dependencies that are dynamic based
516        on configuration information, for example.
517
518        Returns a list of (priority, module name, line number) tuples.
519
520        The line number can be -1 when there is not a known real line number.
521
522        Priorities are defined in mypy.build (but maybe shouldn't be).
523        10 is a good choice for priority.
524        """
525        return []
526
527    def get_type_analyze_hook(self, fullname: str
528                              ) -> Optional[Callable[[AnalyzeTypeContext], Type]]:
529        """Customize behaviour of the type analyzer for given full names.
530
531        This method is called during the semantic analysis pass whenever mypy sees an
532        unbound type. For example, while analysing this code:
533
534            from lib import Special, Other
535
536            var: Special
537            def func(x: Other[int]) -> None:
538                ...
539
540        this method will be called with 'lib.Special', and then with 'lib.Other'.
541        The callback returned by plugin must return an analyzed type,
542        i.e. an instance of `mypy.types.Type`.
543        """
544        return None
545
546    def get_function_signature_hook(self, fullname: str
547                                    ) -> Optional[Callable[[FunctionSigContext], CallableType]]:
548        """Adjust the signature of a function.
549
550        This method is called before type checking a function call. Plugin
551        may infer a better type for the function.
552
553            from lib import Class, do_stuff
554
555            do_stuff(42)
556            Class()
557
558        This method will be called with 'lib.do_stuff' and then with 'lib.Class'.
559        """
560        return None
561
562    def get_function_hook(self, fullname: str
563                          ) -> Optional[Callable[[FunctionContext], Type]]:
564        """Adjust the return type of a function call.
565
566        This method is called after type checking a call. Plugin may adjust the return
567        type inferred by mypy, and/or emit some error messages. Note, this hook is also
568        called for class instantiation calls, so that in this example:
569
570            from lib import Class, do_stuff
571
572            do_stuff(42)
573            Class()
574
575        This method will be called with 'lib.do_stuff' and then with 'lib.Class'.
576        """
577        return None
578
579    def get_method_signature_hook(self, fullname: str
580                                  ) -> Optional[Callable[[MethodSigContext], CallableType]]:
581        """Adjust the signature of a method.
582
583        This method is called before type checking a method call. Plugin
584        may infer a better type for the method. The hook is also called for special
585        Python dunder methods except __init__ and __new__ (use get_function_hook to customize
586        class instantiation). This function is called with the method full name using
587        the class where it was _defined_. For example, in this code:
588
589            from lib import Special
590
591            class Base:
592                def method(self, arg: Any) -> Any:
593                    ...
594            class Derived(Base):
595                ...
596
597            var: Derived
598            var.method(42)
599
600            x: Special
601            y = x[0]
602
603        this method is called with '__main__.Base.method', and then with
604        'lib.Special.__getitem__'.
605        """
606        return None
607
608    def get_method_hook(self, fullname: str
609                        ) -> Optional[Callable[[MethodContext], Type]]:
610        """Adjust return type of a method call.
611
612        This is the same as get_function_hook(), but is called with the
613        method full name (again, using the class where the method is defined).
614        """
615        return None
616
617    def get_attribute_hook(self, fullname: str
618                           ) -> Optional[Callable[[AttributeContext], Type]]:
619        """Adjust type of a class attribute.
620
621        This method is called with attribute full name using the class where the attribute was
622        defined (or Var.info.fullname for generated attributes).
623
624        For classes without __getattr__ or __getattribute__, this hook is only called for
625        names of fields/properties (but not methods) that exist in the instance MRO.
626
627        For classes that implement __getattr__ or __getattribute__, this hook is called
628        for all fields/properties, including nonexistent ones (but still not methods).
629
630        For example:
631
632            class Base:
633                x: Any
634                def __getattr__(self, attr: str) -> Any: ...
635
636            class Derived(Base):
637                ...
638
639            var: Derived
640            var.x
641            var.y
642
643        get_attribute_hook is called with '__main__.Base.x' and '__main__.Base.y'.
644        However, if we had not implemented __getattr__ on Base, you would only get
645        the callback for 'var.x'; 'var.y' would produce an error without calling the hook.
646        """
647        return None
648
649    def get_class_decorator_hook(self, fullname: str
650                                 ) -> Optional[Callable[[ClassDefContext], None]]:
651        """Update class definition for given class decorators.
652
653        The plugin can modify a TypeInfo _in place_ (for example add some generated
654        methods to the symbol table). This hook is called after the class body was
655        semantically analyzed.
656
657        The hook is called with full names of all class decorators, for example
658        """
659        return None
660
661    def get_metaclass_hook(self, fullname: str
662                           ) -> Optional[Callable[[ClassDefContext], None]]:
663        """Update class definition for given declared metaclasses.
664
665        Same as get_class_decorator_hook() but for metaclasses. Note:
666        this hook will be only called for explicit metaclasses, not for
667        inherited ones.
668
669        TODO: probably it should also be called on inherited metaclasses.
670        """
671        return None
672
673    def get_base_class_hook(self, fullname: str
674                            ) -> Optional[Callable[[ClassDefContext], None]]:
675        """Update class definition for given base classes.
676
677        Same as get_class_decorator_hook() but for base classes. Base classes
678        don't need to refer to TypeInfos, if a base class refers to a variable with
679        Any type, this hook will still be called.
680        """
681        return None
682
683    def get_customize_class_mro_hook(self, fullname: str
684                                     ) -> Optional[Callable[[ClassDefContext], None]]:
685        """Customize MRO for given classes.
686
687        The plugin can modify the class MRO _in place_. This method is called
688        with the class full name before its body was semantically analyzed.
689        """
690        return None
691
692    def get_dynamic_class_hook(self, fullname: str
693                               ) -> Optional[Callable[[DynamicClassDefContext], None]]:
694        """Semantically analyze a dynamic class definition.
695
696        This plugin hook allows one to semantically analyze dynamic class definitions like:
697
698            from lib import dynamic_class
699
700            X = dynamic_class('X', [])
701
702        For such definition, this hook will be called with 'lib.dynamic_class'.
703        The plugin should create the corresponding TypeInfo, and place it into a relevant
704        symbol table, e.g. using ctx.api.add_symbol_table_node().
705        """
706        return None
707
708
709T = TypeVar('T')
710
711
712class ChainedPlugin(Plugin):
713    """A plugin that represents a sequence of chained plugins.
714
715    Each lookup method returns the hook for the first plugin that
716    reports a match.
717
718    This class should not be subclassed -- use Plugin as the base class
719    for all plugins.
720    """
721
722    # TODO: Support caching of lookup results (through a LRU cache, for example).
723
724    def __init__(self, options: Options, plugins: List[Plugin]) -> None:
725        """Initialize chained plugin.
726
727        Assume that the child plugins aren't mutated (results may be cached).
728        """
729        super().__init__(options)
730        self._plugins = plugins
731
732    def set_modules(self, modules: Dict[str, MypyFile]) -> None:
733        for plugin in self._plugins:
734            plugin.set_modules(modules)
735
736    def report_config_data(self, ctx: ReportConfigContext) -> Any:
737        config_data = [plugin.report_config_data(ctx) for plugin in self._plugins]
738        return config_data if any(x is not None for x in config_data) else None
739
740    def get_additional_deps(self, file: MypyFile) -> List[Tuple[int, str, int]]:
741        deps = []
742        for plugin in self._plugins:
743            deps.extend(plugin.get_additional_deps(file))
744        return deps
745
746    def get_type_analyze_hook(self, fullname: str
747                              ) -> Optional[Callable[[AnalyzeTypeContext], Type]]:
748        return self._find_hook(lambda plugin: plugin.get_type_analyze_hook(fullname))
749
750    def get_function_signature_hook(self, fullname: str
751                                    ) -> Optional[Callable[[FunctionSigContext], CallableType]]:
752        return self._find_hook(lambda plugin: plugin.get_function_signature_hook(fullname))
753
754    def get_function_hook(self, fullname: str
755                          ) -> Optional[Callable[[FunctionContext], Type]]:
756        return self._find_hook(lambda plugin: plugin.get_function_hook(fullname))
757
758    def get_method_signature_hook(self, fullname: str
759                                  ) -> Optional[Callable[[MethodSigContext], CallableType]]:
760        return self._find_hook(lambda plugin: plugin.get_method_signature_hook(fullname))
761
762    def get_method_hook(self, fullname: str
763                        ) -> Optional[Callable[[MethodContext], Type]]:
764        return self._find_hook(lambda plugin: plugin.get_method_hook(fullname))
765
766    def get_attribute_hook(self, fullname: str
767                           ) -> Optional[Callable[[AttributeContext], Type]]:
768        return self._find_hook(lambda plugin: plugin.get_attribute_hook(fullname))
769
770    def get_class_decorator_hook(self, fullname: str
771                                 ) -> Optional[Callable[[ClassDefContext], None]]:
772        return self._find_hook(lambda plugin: plugin.get_class_decorator_hook(fullname))
773
774    def get_metaclass_hook(self, fullname: str
775                           ) -> Optional[Callable[[ClassDefContext], None]]:
776        return self._find_hook(lambda plugin: plugin.get_metaclass_hook(fullname))
777
778    def get_base_class_hook(self, fullname: str
779                            ) -> Optional[Callable[[ClassDefContext], None]]:
780        return self._find_hook(lambda plugin: plugin.get_base_class_hook(fullname))
781
782    def get_customize_class_mro_hook(self, fullname: str
783                                     ) -> Optional[Callable[[ClassDefContext], None]]:
784        return self._find_hook(lambda plugin: plugin.get_customize_class_mro_hook(fullname))
785
786    def get_dynamic_class_hook(self, fullname: str
787                               ) -> Optional[Callable[[DynamicClassDefContext], None]]:
788        return self._find_hook(lambda plugin: plugin.get_dynamic_class_hook(fullname))
789
790    def _find_hook(self, lookup: Callable[[Plugin], T]) -> Optional[T]:
791        for plugin in self._plugins:
792            hook = lookup(plugin)
793            if hook:
794                return hook
795        return None
796