Skip to content

Commit db74377

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Ensure LspChangeVerifier always normalizes source + expects normalised source files
This removes `useLineEndingsForPlatform = false` from a few more tests, and as part of fixing them, ensures that `LspChangeVerifier` always normalises the expected text, and asserts that all modifies files were modified. This highlighted many more tests that were not normalizing their content (but didn't use `useLineEndingsForPlatform` because they didn't previously call any shared methods that required/asserting normalization. Those tests were also updated. Change-Id: Ica914b6207b3c9fd440de4e0470e50a896dd976d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/443561 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 8e9cb0c commit db74377

34 files changed

+209
-143
lines changed

pkg/analysis_server/lib/src/analysis_server.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,10 @@ abstract class AnalysisServer {
421421
return sessions;
422422
}
423423

424+
/// The default line terminator that should be used by the server when there
425+
/// is no existing EOL to copy.
426+
String get defaultEol => io.Platform.lineTerminator;
427+
424428
/// A table mapping [Folder]s to the [AnalysisDriver]s associated with them.
425429
Map<Folder, analysis.AnalysisDriver> get driverMap =>
426430
contextManager.driverMap;

pkg/analysis_server/lib/src/handler/legacy/edit_get_fixes.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ error.errorCode: ${diagnostic.diagnosticCode}
297297
diagnostic,
298298
content,
299299
node,
300+
defaultEol: server.defaultEol,
300301
);
301302
var fixes = await generator.computeFixes();
302303
if (fixes.isNotEmpty) {

pkg/analysis_server/lib/src/lsp/handlers/code_actions/pubspec.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class PubspecCodeActionsProducer extends AbstractCodeActionsProducer {
8282
error,
8383
content,
8484
node,
85+
defaultEol: server.defaultEol,
8586
);
8687
var fixes = await generator.computeFixes();
8788
if (fixes.isEmpty) {

pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,7 @@ class BulkFixProcessor {
963963
errors[0],
964964
contents,
965965
node,
966+
defaultEol: builder.defaultEol,
966967
);
967968
return await generator.computeFixes();
968969
}

pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:analyzer/src/generated/java_core.dart';
1717
import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
1818
import 'package:analyzer/src/pubspec/validators/missing_dependency_validator.dart';
1919
import 'package:analyzer/src/util/yaml.dart';
20+
import 'package:analyzer_plugin/src/utilities/extensions/string_extension.dart';
2021
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
2122
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
2223
import 'package:yaml/yaml.dart';
@@ -51,35 +52,19 @@ class PubspecFixGenerator {
5152
/// The fixes that were generated.
5253
final List<Fix> fixes = <Fix>[];
5354

54-
/// The end-of-line marker used in the `pubspec.yaml` file.
55-
String? _endOfLine;
55+
/// The end-of-line marker to be used in this `pubspec.yaml` file.
56+
final String endOfLine;
5657

5758
PubspecFixGenerator(
5859
this.resourceProvider,
5960
this.diagnostic,
6061
this.content,
61-
this.node,
62-
) : diagnosticOffset = diagnostic.offset,
63-
diagnosticLength = diagnostic.length,
64-
lineInfo = LineInfo.fromContent(content);
65-
66-
/// Returns the end-of-line marker to use for the `pubspec.yaml` file.
67-
String get endOfLine {
68-
// TODO(brianwilkerson): Share this with CorrectionUtils, probably by
69-
// creating a subclass of CorrectionUtils containing utilities that are
70-
// only dependent on knowing the content of the file. Also consider moving
71-
// this kind of utility into the ChangeBuilder API directly.
72-
var endOfLine = _endOfLine;
73-
if (endOfLine != null) {
74-
return endOfLine;
75-
}
76-
77-
if (content.contains('\r\n')) {
78-
return _endOfLine = '\r\n';
79-
} else {
80-
return _endOfLine = '\n';
81-
}
82-
}
62+
this.node, {
63+
required String defaultEol,
64+
}) : diagnosticOffset = diagnostic.offset,
65+
diagnosticLength = diagnostic.length,
66+
lineInfo = LineInfo.fromContent(content),
67+
endOfLine = content.endOfLine ?? defaultEol;
8368

8469
/// Return the absolute, normalized path to the file in which the error was
8570
/// reported.
@@ -332,10 +317,12 @@ class PubspecFixGenerator {
332317
var section = node[sectionName];
333318
var buffer = StringBuffer();
334319
if (section == null) {
335-
buffer.writeln('$sectionName:');
320+
buffer.write('$sectionName:');
321+
buffer.write(endOfLine);
336322
}
337323
for (var name in packageNames) {
338-
buffer.writeln(' $name: any');
324+
buffer.write(' $name: any');
325+
buffer.write(endOfLine);
339326
}
340327

341328
var offset =

pkg/analysis_server/test/abstract_context.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'dart:io';
6-
75
import 'package:analysis_server/src/protocol_server.dart';
86
import 'package:analysis_server/src/services/correction/assist_internal.dart';
97
import 'package:analysis_server/src/services/correction/fix_internal.dart';
@@ -311,7 +309,7 @@ class AbstractContextTest
311309
}) {
312310
for (var fileEdit in sourceChange.edits) {
313311
var file = getFile(fileEdit.file);
314-
buffer.write('>>>>>>>>>> ${file.posixPath}${Platform.lineTerminator}');
312+
buffer.write('>>>>>>>>>> ${file.posixPath}$testEol');
315313
var current = file.readAsStringSync();
316314
var updated = SourceEdit.applySequence(current, fileEdit.edits);
317315
buffer.write(updated);

pkg/analysis_server/test/abstract_single_unit.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class AbstractSingleUnitTest extends AbstractContextTest {
4444

4545
String get testCode => parsedTestCode.code;
4646
set testCode(String value) {
47-
parsedTestCode = TestCode.parse(
48-
normalizeSource(value),
47+
parsedTestCode = TestCode.parseNormalized(
48+
value,
4949
positionShorthand: allowTestCodeShorthand,
5050
rangeShorthand: allowTestCodeShorthand,
5151
);

pkg/analysis_server/test/lsp/change_verifier.dart

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
6+
57
import 'package:analysis_server/lsp_protocol/protocol.dart';
8+
import 'package:analyzer/src/test_utilities/platform.dart';
9+
import 'package:analyzer_plugin/src/utilities/extensions/string_extension.dart';
610
import 'package:collection/collection.dart';
711
import 'package:test/test.dart';
812

913
import 'request_helpers_mixin.dart';
1014

1115
/// Applies LSP [WorkspaceEdit]s to produce a flattened string describing the
1216
/// new file contents and any create/rename/deletes to use in test expectations.
17+
///
18+
/// Expects all file content to use [testEol] and automatically
19+
/// normalizes expectations to use the same. Does not normalize edits, as line
20+
/// ending differences in edits indicate a bug in the edit creation.
1321
class LspChangeVerifier {
1422
/// Marks that signifies the start of an edit description.
1523
static final editMarkerStart = '>>>>>>>>>>';
@@ -27,11 +35,16 @@ class LspChangeVerifier {
2735
/// The [WorkspaceEdit] being applied/verified.
2836
final WorkspaceEdit edit;
2937

38+
/// The line terminator to use in the output.
39+
final String endOfLine = testEol;
40+
3041
LspChangeVerifier(this.editHelpers, this.edit) {
3142
_applyEdit();
3243
}
3344

3445
void verifyFiles(String expected, {Map<Uri, int>? expectedVersions}) {
46+
expected = normalizeNewlinesForPlatform(expected);
47+
3548
var actual = _toChangeString();
3649
if (actual != expected) {
3750
print('-' * 64);
@@ -182,6 +195,18 @@ class LspChangeVerifier {
182195
String _applyTextEdits(String content, List<TextEdit> changes) =>
183196
editHelpers.applyTextEdits(content, changes);
184197

198+
/// Assert that [input] uses the current platforms line endings.
199+
void _assertLineEnding(String input) {
200+
var actualLineEnding = input.endOfLine;
201+
if (actualLineEnding != null) {
202+
assert(
203+
actualLineEnding == endOfLine,
204+
'Expected line ending ${jsonEncode(endOfLine)} '
205+
'but string uses ${jsonEncode(actualLineEnding)}',
206+
);
207+
}
208+
}
209+
185210
_Change _change(Uri fileUri) => _changes.putIfAbsent(
186211
fileUri,
187212
() => _Change(_getCurrentFileContent(fileUri)),
@@ -197,8 +222,13 @@ class LspChangeVerifier {
197222
expect(edit.textDocument.version, equals(expectedVersion));
198223
}
199224

200-
String? _getCurrentFileContent(Uri uri) =>
201-
editHelpers.getCurrentFileContent(uri);
225+
String? _getCurrentFileContent(Uri uri) {
226+
var content = editHelpers.getCurrentFileContent(uri);
227+
if (content != null) {
228+
_assertLineEnding(content);
229+
}
230+
return content;
231+
}
202232

203233
String _relativeUri(Uri uri) => editHelpers.relativeUri(uri);
204234

@@ -220,7 +250,7 @@ class LspChangeVerifier {
220250
if (content?.isEmpty ?? false) {
221251
buffer.write(' empty');
222252
}
223-
buffer.writeln();
253+
buffer.write(endOfLine);
224254

225255
// Write any annotations.
226256
if (annotations.isNotEmpty) {
@@ -231,7 +261,7 @@ class LspChangeVerifier {
231261
buffer.write(' (${annotation.description})');
232262
}
233263
buffer.write(': ${operations.join(', ')}');
234-
buffer.writeln();
264+
buffer.write(endOfLine);
235265
}
236266
}
237267

@@ -242,7 +272,8 @@ class LspChangeVerifier {
242272
// If the content didn't end with a newline we need to add one, but
243273
// add a marked so it's clear there was no trailing newline.
244274
if (content.isNotEmpty && !content.endsWith('\n')) {
245-
buffer.writeln(editMarkerEnd);
275+
buffer.write(editMarkerEnd);
276+
buffer.write(endOfLine);
246277
}
247278
}
248279
}

pkg/analysis_server/test/lsp/code_actions_mixin.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:analysis_server/lsp_protocol/protocol.dart';
66
import 'package:analysis_server/src/lsp/constants.dart';
77
import 'package:analysis_server/src/lsp/extensions/code_action.dart';
8+
import 'package:analyzer/src/test_utilities/platform.dart';
89
import 'package:analyzer/src/test_utilities/test_code_format.dart';
910
import 'package:collection/collection.dart';
1011
import 'package:test/test.dart';
@@ -80,6 +81,8 @@ mixin CodeActionsTestMixin
8081
String? filePath,
8182
bool openTargetFile = false,
8283
}) async {
84+
content = normalizeNewlinesForPlatform(content);
85+
8386
var action = await expectCodeAction(
8487
TestCode.parse(content),
8588
kind: kind,
@@ -335,6 +338,9 @@ ${LspChangeVerifier.editMarkerStart} ${relativePath(filePath)}
335338
$expected''';
336339
}
337340

341+
content = normalizeNewlinesForPlatform(content);
342+
expected = normalizeNewlinesForPlatform(expected);
343+
338344
var action = await expectCodeActionLiteral(
339345
filePath: filePath,
340346
content,
@@ -375,6 +381,9 @@ ${LspChangeVerifier.editMarkerStart} ${relativePath(filePath)}
375381
$expected''';
376382
}
377383

384+
content = normalizeNewlinesForPlatform(content);
385+
expected = normalizeNewlinesForPlatform(expected);
386+
378387
var commandAction = await expectCommandCodeAction(
379388
filePath: filePath,
380389
content,

pkg/analysis_server/test/lsp/completion_dart_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ typedef ExpectedLabel =
6464
abstract class AbstractCompletionTest extends AbstractLspAnalysisServerTest
6565
with CompletionTestMixin {
6666
late String content;
67-
late final code = TestCode.parseNormalized(content);
67+
late final TestCode code = TestCode.parseNormalized(content);
6868

6969
AbstractCompletionTest() {
7070
defaultInitializationOptions = {
@@ -5384,7 +5384,7 @@ stle^
53845384
abstract class SnippetCompletionTest extends AbstractLspAnalysisServerTest
53855385
with CompletionTestMixin {
53865386
late String content;
5387-
late final code = TestCode.parseNormalized(content);
5387+
late final TestCode code = TestCode.parseNormalized(content);
53885388

53895389
/// Expect that there is a snippet for [prefix] at [position] with the label
53905390
/// [label] and return the results of applying it to [content].

0 commit comments

Comments
 (0)