[analysis_server] Enable test newline normalization by default

+ fix several failing tests with this enabled.

See https://github.com/dart-lang/sdk/issues/60234

Change-Id: Ie71e1655bf2ab8ac651bfcf803884741863b42c1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/423801
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Danny Tuppeny
2025-04-22 10:23:12 -07:00
committed by Commit Queue
parent 226ec8413e
commit 59587b0e27
15 changed files with 75 additions and 46 deletions
@@ -34,7 +34,7 @@ class AbstractContextTest
static final ByteStore _byteStore = MemoryByteStore();
/// Whether to rewrite line endings in test code based on platform.
bool useLineEndingsForPlatform = false;
bool useLineEndingsForPlatform = true;
final Map<String, String> _declaredVariables = {};
AnalysisContextCollectionImpl? _analysisContextCollection;
@@ -3,10 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/error_or.dart';
import 'package:analysis_server/src/lsp/source_edits.dart';
import 'package:analyzer/src/test_utilities/test_code_format.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -319,13 +321,14 @@ Delete 1:24-1:26
/// https://github.com/Dart-Code/Dart-Code/issues/5200
Future<void> test_minimalEdits_comment_multiLine_trailingWhitespace() async {
// The initial content has a trailing space on the end of the comment.
const startContent = r'''
var startContent =
TestCode.parse(r'''
/**
* line with trailing whitespace
* line with trailing whitespace
* line with trailing whitespace /**/
* line with trailing whitespace /**/
*/
int? a;
''';
''').code;
// We expect the trailing spaces to be removed.
const endContent = r'''
/**
@@ -619,6 +622,9 @@ void g() {
String? expectedFormatResult,
Range? range,
}) async {
start = normalizeSource(start);
end = normalizeSource(end);
await parseTestCode(start);
var edits =
generateEditsForFormatting(testParsedResult, range: range).result!;
@@ -639,10 +645,26 @@ void g() {
String? expectedFormatResult,
Range? range,
}) async {
start = start.trim();
end = end.trim();
start = normalizeSource(start.trim());
end = normalizeSource(end.trim());
if (expectedFormatResult != null) {
expectedFormatResult = normalizeSource(expectedFormatResult.trim());
}
expected = expected.trim();
expectedFormatResult = expectedFormatResult?.trim();
// Expectation descriptions are always written with literal newlines as '\n'
// so on Windows we will need to update the expectation to '\r\n' before
// comparing.
expect(
expected,
isNot(contains(r'\r')),
reason:
'Expectations should always be written with literal '
r"'\n' to indicate newlines regardless of platform",
);
if (Platform.isWindows) {
expected = expected.replaceAll(r'\n', r'\r\n');
}
await parseTestCode(start);
var edits = generateMinimalEdits(testParsedResult, end, range: range);
@@ -37,7 +37,7 @@ class PostfixCompletionTest extends AbstractSingleUnitTest {
if (change.edits.isNotEmpty) {
// We use a carat in the expected code to prevent lines containing only
// whitespace from being made empty.
var expectedCode = TestCode.parse(expected);
var expectedCode = TestCode.parse(normalizeSource(expected));
var resultCode = SourceEdit.applySequence(
testCode,
change.edits[0].edits,
@@ -68,7 +68,7 @@ class PostfixCompletionTest extends AbstractSingleUnitTest {
}
Future<void> _prepareProcessor(String key, String code) async {
testCodeCode = TestCode.parse(code);
testCodeCode = TestCode.parse(normalizeSource(code));
verifyNoTestUnitErrors = false;
await resolveTestCode(testCodeCode.code);
@@ -1001,7 +1001,7 @@ class NonLibraryAnnotation {
);
var edits = organizer.organize();
var result = SourceEdit.applySequence(testCode, edits);
expect(result, expectedCode);
expect(result, normalizeSource(expectedCode));
}
Future<void> _computeUnitAndErrors(String code) async {
@@ -1793,6 +1793,6 @@ void f() {}
);
var edits = sorter.sort();
var result = SourceEdit.applySequence(testCode, edits);
expect(result, expectedCode);
expect(result, normalizeSource(expectedCode));
}
}
@@ -137,8 +137,9 @@ class ColorComputerTest extends AbstractContextTest {
Map<String, int> expectedColorValues, {
String? otherCode,
}) async {
dartCode = _withCommonImports(dartCode);
otherCode = otherCode != null ? _withCommonImports(otherCode) : null;
dartCode = _withCommonImportsNormalized(dartCode);
otherCode =
otherCode != null ? _withCommonImportsNormalized(otherCode) : null;
newFile(testPath, dartCode);
if (otherCode != null) {
@@ -460,10 +461,12 @@ final a = [[COLOR]];
await checkAllColors(testCode);
}
String _withCommonImports(String code) => '''
String _withCommonImportsNormalized(String code) {
return normalizeSource('''
import 'package:flutter/cupertino.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/material.dart';
$code''';
$code''');
}
}
@@ -1041,7 +1041,7 @@ void f() {}
}
Future<void> _computeRegions(String sourceContent) async {
code = TestCode.parse(sourceContent);
code = TestCode.parse(normalizeSource(sourceContent));
var file = newFile(sourcePath, code.code);
var result = await getResolvedUnit(file);
var computer = DartUnitFoldingComputer(result.lineInfo, result.unit);
@@ -110,7 +110,7 @@ void f() {
String content, {
bool hasErrors = false,
}) async {
this.content = content;
this.content = content = normalizeSource(content);
var file = newFile(sourcePath, content);
var result = await getResolvedUnit(file);
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
import 'package:analyzer/src/test_utilities/test_code_format.dart';
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -1096,11 +1095,8 @@ abstract class FeatureComputerTest extends AbstractSingleUnitTest {
bool verifyNoTestUnitErrors = false;
Future<void> completeIn(String content) async {
var code = TestCode.parse(content);
cursorIndex = code.position.offset;
content = code.code;
await resolveTestCode(code.code);
await resolveTestCode(content);
cursorIndex = parsedTestCode.position.offset;
completionTarget = CompletionTarget.forOffset(testUnit, cursorIndex);
}
}
@@ -71,13 +71,13 @@ abstract class AssistProcessorTest extends AbstractSingleUnitTest {
int index = 0,
}) async {
_setPositionOrRange(index);
if (useLineEndingsForPlatform) {
expected = normalizeNewlinesForPlatform(expected);
additionallyChangedFiles = additionallyChangedFiles?.map(
(key, value) =>
MapEntry(key, value.map(normalizeNewlinesForPlatform).toList()),
);
}
expected = normalizeNewlinesForPlatform(expected);
additionallyChangedFiles = additionallyChangedFiles?.map(
(key, value) =>
MapEntry(key, value.map(normalizeNewlinesForPlatform).toList()),
);
// Remove any marker in the expected code. We allow markers to prevent an
// otherwise empty line from having the leading whitespace be removed.
expected = TestCode.parse(expected).code;
@@ -139,12 +139,6 @@ abstract class AssistProcessorTest extends AbstractSingleUnitTest {
}).toList();
}
@override
void setUp() {
super.setUp();
useLineEndingsForPlatform = true;
}
/// Computes assists and verifies that there is an assist of the given kind.
Future<Assist> _assertHasAssist() async {
var assists = await _computeAssists();
@@ -113,7 +113,7 @@ abstract class BulkFixProcessorTest extends AbstractSingleUnitTest {
var fixes = (await processor.fixPubspec([analysisContext])).edits;
var edits = [for (var fix in fixes) ...fix.edits];
var result = SourceEdit.applySequence(original, edits);
expect(result, expected);
expect(result, normalizeSource(expected));
}
Future<void> assertFormat(String expectedCode) async {
@@ -124,7 +124,7 @@ abstract class BulkFixProcessorTest extends AbstractSingleUnitTest {
var fileEdits = change.edits;
expect(fileEdits, hasLength(1));
resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits);
expect(resultCode, expectedCode);
expect(resultCode, normalizeSource(expectedCode));
}
Future<void> assertHasFix(String expected, {bool isParse = false}) async {
@@ -136,7 +136,7 @@ abstract class BulkFixProcessorTest extends AbstractSingleUnitTest {
var fileContent = testCode;
resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits);
expect(resultCode, expected);
expect(resultCode, normalizeSource(expected));
}
Future<void> assertNoFix() async {
@@ -153,7 +153,7 @@ abstract class BulkFixProcessorTest extends AbstractSingleUnitTest {
var fileEdits = change.edits;
expect(fileEdits, hasLength(1));
resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits);
expect(resultCode, expectedCode);
expect(resultCode, normalizeSource(expectedCode));
}
/// Computes fixes for the specified [testUnit].
@@ -307,8 +307,6 @@ void f() {
}
Future<void> test_hierarchy() async {
useLineEndingsForPlatform = false;
await resolveTestCode('''
import 'package:flutter/material.dart';
@@ -27,7 +27,7 @@ class WidgetDescriptionBase extends AbstractSingleUnitTest {
testAnalysisResult.content,
fileEdit.edits,
);
expect(actual, expected);
expect(actual, normalizeSource(expected));
}
void assertPropertyJsonText(
@@ -178,7 +178,7 @@ class C {}
void _assertTokens(List<String> expected) {
expect(
result.unit.fileHeader.map((token) => token.lexeme),
orderedEquals(expected),
orderedEquals(expected.map(normalizeSource)),
);
}
}
@@ -2,6 +2,8 @@
// 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:io';
import 'package:analysis_server_plugin/src/utilities/selection.dart';
import 'package:analyzer/src/test_utilities/test_code_format.dart';
import 'package:test/test.dart';
@@ -1409,6 +1411,20 @@ nodesInRange
void _assertSelection(_CodeSelection selection, String expected) {
var buffer = StringBuffer();
_writeSelectionToBuffer(buffer, selection);
// Expectation descriptions are always written with literal newlines as '\n'
// so on Windows we will need to update the expectation to '\r\n' before
// comparing.
expect(
expected,
isNot(contains(r'\r')),
reason:
r'Expectations should always be written with literal '
"'\n' to indicate newlines regardless of platform",
);
if (Platform.isWindows) {
expected = expected.replaceAll(r'\n', r'\r\n');
}
_assertTextExpectation(buffer.toString(), expected);
}
@@ -1423,7 +1439,7 @@ nodesInRange
}
Future<_CodeSelection> _computeSelection(String annotatedCode) async {
var testCode = TestCode.parse(annotatedCode);
var testCode = TestCode.parse(normalizeSource(annotatedCode));
expect(testCode.positions, isEmpty);
var range = testCode.range.sourceRange;