Chromium Code Reviews| Index: tests/compiler/dart2js/analyze_dart2js_helpers_test.dart |
| diff --git a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9262b113a2df2823a5e904f4adfe7d10197e4b50 |
| --- /dev/null |
| +++ b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart |
| @@ -0,0 +1,236 @@ |
| +// Copyright (c) 2015, 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 dart2js.analyze_helpers.test; |
| + |
| +import 'dart:io'; |
| + |
| +import 'package:async_helper/async_helper.dart'; |
| +import 'package:compiler/compiler_new.dart' show |
| + Diagnostic; |
| +import 'package:compiler/src/apiimpl.dart' show |
| + Compiler; |
| +import 'package:compiler/src/constants/expressions.dart' show |
| + ConstructedConstantExpression; |
| +import 'package:compiler/src/dart_types.dart' show |
| + InterfaceType; |
| +import 'package:compiler/src/diagnostics/source_span.dart' show |
| + SourceSpan; |
| +import 'package:compiler/src/elements/elements.dart'; |
| +import 'package:compiler/src/filenames.dart' show |
| + nativeToUriPath; |
| +import 'package:compiler/src/resolution/semantic_visitor.dart'; |
| +import 'package:compiler/src/resolution/tree_elements.dart' show |
| + TreeElements; |
| +import 'package:compiler/src/source_file_provider.dart' show |
| + FormattingDiagnosticHandler; |
| +import 'package:compiler/src/tree/tree.dart'; |
| +import 'package:compiler/src/universe/universe.dart' show |
| + CallStructure; |
| +import 'package:expect/expect.dart'; |
| + |
| +import 'memory_compiler.dart'; |
| + |
| +main(List<String> arguments) { |
| + bool verbose = arguments.contains('-v'); |
| + |
| + List<String> options = <String>[ |
| + '--analyze-only', |
| + '--analyze-main', |
| + '--categories=Client,Server']; |
| + if (verbose) { |
| + options.add('--verbose'); |
| + } |
| + asyncTest(() async { |
| + Compiler compiler = compilerFor( |
| + options: options, showDiagnostics: verbose); |
| + FormattingDiagnosticHandler diagnostics = |
| + new FormattingDiagnosticHandler(compiler.provider); |
| + HelperAnalyzer analyzer = new HelperAnalyzer(diagnostics); |
| + Directory dir = |
| + new Directory.fromUri(Uri.base.resolve('pkg/compiler/lib/')); |
| + for (FileSystemEntity entity in dir.listSync(recursive: true)) { |
| + if (entity is File && entity.path.endsWith('.dart')) { |
| + Uri file = Uri.base.resolve(nativeToUriPath(entity.path)); |
| + if (verbose) { |
| + print('---- analyzing $file ----'); |
| + } |
| + LibraryElement library = await compiler.analyzeUri(file); |
| + if (library != null) { |
| + library.forEachLocalMember((Element element) { |
| + if (element is ClassElement) { |
| + element.forEachLocalMember((AstElement member) { |
| + analyzer.analyze(member.resolvedAst); |
| + }); |
| + } else if (element is MemberElement) { |
| + analyzer.analyze(element.resolvedAst); |
| + } |
| + }); |
| + } |
| + } |
| + } |
| + Expect.isTrue(analyzer.errors.isEmpty, "Errors found."); |
| + }); |
| +} |
| + |
| +class HelperAnalyzer extends TraversalVisitor { |
| + final FormattingDiagnosticHandler diagnostics; |
| + List<SourceSpan> errors = <SourceSpan>[]; |
| + |
| + ResolvedAst resolvedAst; |
| + |
| + @override |
| + TreeElements get elements => resolvedAst.elements; |
| + |
| + AnalyzableElement get analyzedElement => resolvedAst.element; |
| + |
| + HelperAnalyzer(this.diagnostics) : super(null); |
| + |
| + @override |
| + void apply(Node node, [_]) { |
| + node.accept(this); |
| + } |
| + |
| + void analyze(ResolvedAst resolvedAst) { |
| + if (resolvedAst.node == null) { |
| + // Skip synthesized members. |
| + return; |
| + } |
| + this.resolvedAst = resolvedAst; |
| + //print('analyze:$resolvedAst'); |
|
karlklose
2015/08/28 11:38:26
Remove or put into verbose block.
Johnni Winther
2015/08/28 11:45:51
Done.
|
| + apply(resolvedAst.node); |
| + this.resolvedAst = null; |
| + } |
| + |
| + bool isHelper(Element element) { |
| + Uri uri = element.library.canonicalUri; |
| + return uri.path.endsWith('src/helpers/helpers.dart'); |
| + } |
| + |
| + void checkAccess(Node node, MemberElement element) { |
| + if (isHelper(element) && !isHelper(analyzedElement)) { |
| + Uri uri = analyzedElement.implementation.sourcePosition.uri; |
| + SourceSpan span = new SourceSpan.fromNode(uri, node); |
| + diagnostics.report(null, span.uri, span.begin, span.end, |
| + "Helper used in production code.", |
| + Diagnostic.ERROR); |
| + errors.add(span); |
| + } |
| + } |
| + |
| + @override |
| + void visitTopLevelFieldInvoke( |
| + Send node, |
| + FieldElement field, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, field); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitTopLevelGetterInvoke( |
| + Send node, |
| + GetterElement getter, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, getter); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitTopLevelFunctionInvoke( |
| + Send node, |
| + MethodElement method, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, method); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitTopLevelFieldGet( |
| + Send node, |
| + FieldElement field, |
| + _) { |
| + checkAccess(node, field); |
| + } |
| + |
| + @override |
| + void visitTopLevelGetterGet( |
| + Send node, |
| + GetterElement getter, |
| + _) { |
| + checkAccess(node, getter); |
| + } |
| + |
| + @override |
| + void visitTopLevelFunctionGet( |
| + Send node, |
| + MethodElement method, |
| + _) { |
| + checkAccess(node, method); |
| + } |
| + |
| + @override |
| + void visitGenerativeConstructorInvoke( |
| + NewExpression node, |
| + ConstructorElement constructor, |
| + InterfaceType type, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, constructor); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitRedirectingGenerativeConstructorInvoke( |
| + NewExpression node, |
| + ConstructorElement constructor, |
| + InterfaceType type, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, constructor); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitFactoryConstructorInvoke( |
| + NewExpression node, |
| + ConstructorElement constructor, |
| + InterfaceType type, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, constructor); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitRedirectingFactoryConstructorInvoke( |
| + NewExpression node, |
| + ConstructorElement constructor, |
| + InterfaceType type, |
| + ConstructorElement effectiveTarget, |
| + InterfaceType effectiveTargetType, |
| + NodeList arguments, |
| + CallStructure callStructure, |
| + _) { |
| + checkAccess(node, constructor); |
| + apply(arguments); |
| + } |
| + |
| + @override |
| + void visitConstConstructorInvoke( |
| + NewExpression node, |
| + ConstructedConstantExpression constant, |
| + _) { |
| + checkAccess(node, constant.target); |
| + } |
| +} |