// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. library kernel.transformations.scanner; import '../ast.dart'; abstract class Scanner { final Scanner? next; Scanner(this.next); bool predicate(X x); ScanResult scan(TreeNode node); } class ScanResult { Map?> targets = new Map(); Map? errors; @override String toString() => 'ScanResult<$X,$Y>'; } class ScanError {} abstract class ClassScanner implements Scanner { @override final Scanner? next; ClassScanner(this.next); @override bool predicate(Class node); @override ScanResult scan(TreeNode node) { ScanResult result = new ScanResult(); if (node is Class) { if (predicate(node)) { result.targets[node] = next?.scan(node); // TODO(cstefantsova): set result.errors when specification is landed, // same with all other places where targets is set } } else if (node is Library) { _scanLibrary(node, result); } else if (node is Component) { _scanComponent(node, result); } return result; } void _scanLibrary(Library library, ScanResult result) { for (Class cls in library.classes) { if (predicate(cls)) { result.targets[cls] = next?.scan(cls); } } } void _scanComponent(Component component, ScanResult result) { for (Library library in component.libraries) { _scanLibrary(library, result); } } } abstract class FieldScanner implements Scanner { @override final Scanner? next; FieldScanner(this.next); @override bool predicate(Field node); @override ScanResult scan(TreeNode node) { ScanResult result = new ScanResult(); if (node is Field) { _scanField(node, result); } else if (node is Class) { _scanClass(node, result); } else if (node is Library) { _scanLibrary(node, result); } else if (node is Component) { _scanComponent(node, result); } return result; } void _scanField(Field field, ScanResult result) { if (predicate(field)) { result.targets[field] = next?.scan(field); } } void _scanClass(Class cls, ScanResult result) { for (Field field in cls.fields) { _scanField(field, result); } } void _scanLibrary(Library library, ScanResult result) { for (Class cls in library.classes) { _scanClass(cls, result); } for (Field field in library.fields) { _scanField(field, result); } } void _scanComponent(Component component, ScanResult result) { for (Library library in component.libraries) { _scanLibrary(library, result); } } } abstract class MemberScanner implements Scanner { @override final Scanner? next; MemberScanner(this.next); @override bool predicate(Member node); @override ScanResult scan(TreeNode node) { ScanResult result = new ScanResult(); if (node is Member) { _scanMember(node, result); } else if (node is Class) { _scanClass(node, result); } else if (node is Library) { _scanLibrary(node, result); } else if (node is Component) { _scanComponent(node, result); } return result; } void _scanMember(Member member, ScanResult result) { if (predicate(member)) { result.targets[member] = next?.scan(member); } } void _scanClass(Class cls, ScanResult result) { for (Member member in cls.members) { _scanMember(member, result); } } void _scanLibrary(Library library, ScanResult result) { for (Class cls in library.classes) { _scanClass(cls, result); } for (Member member in library.members) { _scanMember(member, result); } } void _scanComponent(Component component, ScanResult result) { for (Library library in component.libraries) { _scanLibrary(library, result); } } } abstract class ProcedureScanner implements Scanner { @override final Scanner? next; ProcedureScanner(this.next); @override bool predicate(Procedure node); @override ScanResult scan(TreeNode node) { ScanResult result = new ScanResult(); if (node is Procedure) { _scanProcedure(node, result); } else if (node is Class) { _scanClass(node, result); } else if (node is Library) { _scanLibrary(node, result); } else if (node is Component) { _scanComponent(node, result); } return result; } void _scanProcedure(Procedure procedure, ScanResult result) { if (predicate(procedure)) { result.targets[procedure] = next?.scan(procedure); } } void _scanClass(Class cls, ScanResult result) { for (Procedure procedure in cls.procedures) { _scanProcedure(procedure, result); } } void _scanLibrary(Library library, ScanResult result) { for (Class cls in library.classes) { _scanClass(cls, result); } for (Procedure procedure in library.procedures) { _scanProcedure(procedure, result); } } void _scanComponent(Component component, ScanResult result) { for (Library library in component.libraries) { _scanLibrary(library, result); } } } abstract class ExpressionScanner extends RecursiveResultVisitor implements Scanner { @override final Scanner? next; ScanResult? _result; ExpressionScanner(this.next); @override bool predicate(Expression node); @override ScanResult scan(TreeNode node) { ScanResult result = _result = new ScanResult(); node.accept(this); _result = null; return result; } void visitExpression(Expression node) { if (predicate(node)) { _result!.targets[node] = next?.scan(node); // TODO: Update result.errors. } } } abstract class MethodInvocationScanner extends RecursiveVisitor implements Scanner { @override final Scanner? next; ScanResult? _result; MethodInvocationScanner(this.next); @override bool predicate(InstanceInvocationExpression node); @override ScanResult scan(TreeNode node) { ScanResult result = _result = new ScanResult(); node.accept(this); _result = null; return result; } @override void visitInstanceInvocation(InstanceInvocation node) { if (predicate(node)) { _result!.targets[node] = next?.scan(node); // TODO: Update result.errors. } } }