| # Copyright 2019 The Fuchsia 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 typing import Sequence, TypeVar, Generic, List, Tuple, Callable, Dict | 
 |  | 
 | from difl.ir import Declaration | 
 | from difl.changes import Change, DeclAdded, DeclRemoved | 
 | from difl.comparator import Comparator | 
 |  | 
 | D = TypeVar('D', bound=Declaration) | 
 |  | 
 |  | 
 | def intersect_changes( | 
 |         before: Sequence[D], | 
 |         after: Sequence[D], | 
 |         compare: Callable[[D, D, Comparator], List[Change]], | 
 |         comparator: Comparator, | 
 |         include_decl_added_and_decl_removed=True) -> List[Change]: | 
 |     # dictionaries of declarations by name | 
 |     before_by_name = {d.name: d for d in before} | 
 |     after_by_name = {d.name: d for d in after} | 
 |     # immutable sets of declaration names | 
 |     before_names = frozenset(before_by_name.keys()) | 
 |     after_names = frozenset(after_by_name.keys()) | 
 |  | 
 |     changes: List[Change] = [] | 
 |  | 
 |     if include_decl_added_and_decl_removed: | 
 |         for decl in [after_by_name[n] for n in after_names - before_names]: | 
 |             changes.append(DeclAdded(before=None, after=decl)) | 
 |         for decl in [before_by_name[n] for n in before_names - after_names]: | 
 |             changes.append(DeclRemoved(before=decl, after=None)) | 
 |     for before_decl, after_decl in [ | 
 |         (before_by_name[n], after_by_name[n]) | 
 |             for n in before_names.intersection(after_names) | 
 |     ]: | 
 |         changes.extend(compare(before_decl, after_decl, comparator)) | 
 |  | 
 |     return changes |