// 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 CompilerImpl;
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/constants/expressions.dart'
    show ConstructedConstantExpression;
import 'package:compiler/src/elements/resolution_types.dart'
    show ResolutionInterfaceType;
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/call_structure.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>[
    Flags.analyzeOnly,
    Flags.analyzeMain,
    '--categories=Client,Server'
  ];
  if (verbose) {
    options.add(Flags.verbose);
  }
  asyncTest(() async {
    CompilerImpl compiler =
        compilerFor(options: options, showDiagnostics: verbose);
    FormattingDiagnosticHandler diagnostics =
        new FormattingDiagnosticHandler(compiler.provider);
    Directory dir =
        new Directory.fromUri(Uri.base.resolve('pkg/compiler/lib/'));
    String helpersUriPrefix = dir.uri.resolve('src/helpers/').toString();
    HelperAnalyzer analyzer = new HelperAnalyzer(diagnostics, helpersUriPrefix);
    LibraryElement helperLibrary;
    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) {
          if (library.libraryName == 'dart2js.helpers') {
            helperLibrary = library;
          }
          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.isNotNull(helperLibrary, 'Helper library not found');
    Expect.isTrue(analyzer.isHelper(helperLibrary),
        "Helper library $helperLibrary is not considered a helper.");
    Expect.isTrue(analyzer.errors.isEmpty, "Errors found.");
  });
}

class HelperAnalyzer extends TraversalVisitor {
  final FormattingDiagnosticHandler diagnostics;
  final String helpersUriPrefix;
  List<SourceSpan> errors = <SourceSpan>[];

  ResolvedAst resolvedAst;

  @override
  TreeElements get elements => resolvedAst.elements;

  AnalyzableElement get analyzedElement => resolvedAst.element;

  HelperAnalyzer(this.diagnostics, this.helpersUriPrefix) : super(null);

  @override
  void apply(Node node, [_]) {
    node.accept(this);
  }

  void analyze(ResolvedAst resolvedAst) {
    if (resolvedAst.kind != ResolvedAstKind.PARSED) {
      // Skip synthesized members.
      return;
    }
    this.resolvedAst = resolvedAst;
    apply(resolvedAst.node);
    this.resolvedAst = null;
  }

  bool isHelper(Element element) {
    Uri uri = element.library.canonicalUri;
    return '$uri'.startsWith(helpersUriPrefix);
  }

  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,
      ResolutionInterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    checkAccess(node, constructor);
    apply(arguments);
  }

  @override
  void visitRedirectingGenerativeConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      ResolutionInterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    checkAccess(node, constructor);
    apply(arguments);
  }

  @override
  void visitFactoryConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      ResolutionInterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    checkAccess(node, constructor);
    apply(arguments);
  }

  @override
  void visitRedirectingFactoryConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      ResolutionInterfaceType type,
      ConstructorElement effectiveTarget,
      ResolutionInterfaceType effectiveTargetType,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    checkAccess(node, constructor);
    apply(arguments);
  }

  @override
  void visitConstConstructorInvoke(
      NewExpression node, ConstructedConstantExpression constant, _) {
    checkAccess(node, constant.target);
  }
}
