// Copyright (c) 2014, 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.

import 'dart:async';

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../analysis_abstract.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(GetErrorsTest);
  });
}

@reflectiveTest
class GetErrorsTest extends AbstractAnalysisTest {
  static const String requestId = 'test-getError';

  @override
  void setUp() {
    super.setUp();
    server.handlers = [
      new AnalysisDomainHandler(server),
    ];
    createProject();
  }

  test_afterAnalysisComplete() async {
    addTestFile('''
main() {
  print(42)
}
''');
    await waitForTasksFinished();
    List<AnalysisError> errors = await _getErrors(testFile);
    expect(errors, hasLength(1));
  }

  test_errorInPart() async {
    String libPath = join(testFolder, 'main.dart');
    String partPath = join(testFolder, 'main_part.dart');
    newFile(libPath, content: r'''
library main;
part 'main_part.dart';
class A {}
''');
    newFile(partPath, content: r'''
part of main;
class A {}
''');
    await waitForTasksFinished();
    {
      List<AnalysisError> libErrors = await _getErrors(libPath);
      expect(libErrors, isEmpty);
    }
    {
      List<AnalysisError> partErrors = await _getErrors(partPath);
      expect(partErrors, hasLength(1));
    }
  }

  @failingTest
  test_fileWithoutContext() {
    // Broken under the new driver.
    String file = convertPath('/outside.dart');
    newFile(file, content: '''
main() {
  print(42);
}
''');
    return _checkInvalid(file);
  }

  test_hasErrors() async {
    addTestFile('''
main() {
  print(42)
}
''');
    List<AnalysisError> errors = await _getErrors(testFile);
    expect(errors, hasLength(1));
    {
      AnalysisError error = errors[0];
      expect(error.severity, AnalysisErrorSeverity.ERROR);
      expect(error.type, AnalysisErrorType.SYNTACTIC_ERROR);
      expect(error.location.file, testFile);
      expect(error.location.startLine, 2);
    }
  }

  test_noErrors() async {
    addTestFile('''
main() {
  print(42);
}
''');
    List<AnalysisError> errors = await _getErrors(testFile);
    expect(errors, isEmpty);
  }

  Future _checkInvalid(String file) async {
    Request request = _createGetErrorsRequest(file);
    Response response = await serverChannel.sendRequest(request);
    expect(response.error, isNotNull);
    expect(response.error.code, RequestErrorCode.GET_ERRORS_INVALID_FILE);
  }

  Request _createGetErrorsRequest(String file) {
    return new AnalysisGetErrorsParams(file).toRequest(requestId);
  }

  Future<List<AnalysisError>> _getErrors(String file) async {
    Request request = _createGetErrorsRequest(file);
    Response response = await serverChannel.sendRequest(request);
    return new AnalysisGetErrorsResult.fromResponse(response).errors;
  }
}
