Skip to content

Commit

Permalink
Version 3.8.0-2.0.dev
Browse files Browse the repository at this point in the history
Merge 9f465e5 into dev
  • Loading branch information
Dart CI committed Jan 17, 2025
2 parents f11b24d + 9f465e5 commit ae8d812
Show file tree
Hide file tree
Showing 23 changed files with 841 additions and 254 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ vars = {

# Prefer to use hashes of binaryen that have been reviewed & rolled into g3.
"binaryen_rev" : "3f6831c0bd147ae1ae0ab1d9187d37bce7cca38b",
"boringssl_rev": "822902749a5956bba09c7e9e451104e8a74f02c5",
"boringssl_rev": "5a2194f43d8801335e4b20040156686eb4247b22",
"browser-compat-data_tag": "ac8cae697014da1ff7124fba33b0b4245cc6cd1b", # v1.0.22
"cpu_features_rev": "936b9ab5515dead115606559502e3864958f7f6e",
"devtools_rev": "8762b31f0d0ffeea6449fd02740e9ce7acb32503",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2025, 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 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/ignore_comments/ignore_info.dart';
import 'package:analyzer/src/utilities/extensions/ast.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';

class RemoveIgnore extends ResolvedCorrectionProducer {
String _diagnosticName = '';
RemoveIgnore({required super.context});

@override
CorrectionApplicability get applicability =>
CorrectionApplicability.singleLocation;

@override
List<String> get fixArguments => [_diagnosticName];

@override
FixKind get fixKind => DartFixKind.REMOVE_IGNORED_DIAGNOSTIC;

@override
Future<void> compute(ChangeBuilder builder) async {
var diagnostic = this.diagnostic;
if (diagnostic == null) return;

var diagnosticOffset = diagnostic.problemMessage.offset;

var comment = node.commentTokenCovering(diagnosticOffset);
if (comment is! CommentToken) return;

SourceRange? rangeToDelete;

var ignoredElements = comment.ignoredElements.toList();

for (var (index, ignoredElement) in ignoredElements.indexed) {
if (ignoredElement is! IgnoredDiagnosticName) continue;

var ignoredElementOffset = ignoredElement.offset;
if (ignoredElement.offset == diagnosticOffset) {
_diagnosticName = ignoredElement.name;
var scanBack = index != 0;
var commentText = comment.lexeme;
if (scanBack) {
// Scan back for a preceding comma:
for (var offset = ignoredElementOffset; offset > -1; --offset) {
if (commentText[offset] == ',') {
var backSteps = ignoredElementOffset - offset;
rangeToDelete = SourceRange(
diagnosticOffset - backSteps,
_diagnosticName.length + backSteps,
);
break;
}
}
} else {
// Scan forward for a trailing comma:
var chars = commentText.substring(ignoredElementOffset).indexOf(',');
if (chars == -1) return;

// Eat the comma
chars++;

// Eat a trailing space if needed
if (commentText[ignoredElementOffset + chars] == ' ') chars++;

rangeToDelete = SourceRange(ignoredElementOffset, chars);
}
}
}

if (rangeToDelete != null) {
await builder.addDartFileEdit(file, (builder) {
builder.addDeletion(rangeToDelete!);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2424,13 +2424,15 @@ LintCode.unnecessary_getters_setters:
LintCode.unnecessary_ignore:
status: needsFix
notes: |-
Remove the ignore comment (or one code in the comment).
Remove the ignore comment.
LintCode.unnecessary_ignore_file:
status: needsFix
notes: |-
Remove the ignore comment.
LintCode.unnecessary_ignore_name:
status: needsFix
status: hasFix
LintCode.unnecessary_ignore_name_file:
status: needsFix
status: hasFix
LintCode.unnecessary_lambdas:
status: hasFix
LintCode.unnecessary_late:
Expand Down
5 changes: 5 additions & 0 deletions pkg/analysis_server/lib/src/services/correction/fix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,11 @@ abstract final class DartFixKind {
DartFixKindPriority.inFile,
"Remove unnecessary '??' operators everywhere in file",
);
static const REMOVE_IGNORED_DIAGNOSTIC = FixKind(
'dart.fix.remove.ignored.diagnostic',
DartFixKindPriority.standard,
'Remove {0}',
);
static const REMOVE_INVOCATION = FixKind(
'dart.fix.remove.invocation',
DartFixKindPriority.standard,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ import 'package:analysis_server/src/services/correction/dart/remove_empty_else.d
import 'package:analysis_server/src/services/correction/dart/remove_empty_statement.dart';
import 'package:analysis_server/src/services/correction/dart/remove_extends_clause.dart';
import 'package:analysis_server/src/services/correction/dart/remove_if_null_operator.dart';
import 'package:analysis_server/src/services/correction/dart/remove_ignore.dart';
import 'package:analysis_server/src/services/correction/dart/remove_initializer.dart';
import 'package:analysis_server/src/services/correction/dart/remove_interpolation_braces.dart';
import 'package:analysis_server/src/services/correction/dart/remove_invocation.dart';
Expand Down Expand Up @@ -485,6 +486,11 @@ final _builtInLintProducers = <LintCode, List<ProducerGenerator>>{
LinterLintCode.unnecessary_final_with_type: [ReplaceFinalWithVar.new],
LinterLintCode.unnecessary_final_without_type: [ReplaceFinalWithVar.new],
LinterLintCode.unnecessary_getters_setters: [MakeFieldPublic.new],
LinterLintCode.unnecessary_ignore_name: [RemoveIgnore.new],
LinterLintCode.unnecessary_ignore_name_file: [RemoveIgnore.new],
// TODO(pq): add =>
// LinterLintCode.unnecessary_ignore: [RemoveComment.new],
// LinterLintCode.unnecessary_ignore_file: [RemoveComment.new],
LinterLintCode.unnecessary_lambdas: [ReplaceWithTearOff.new],
LinterLintCode.unnecessary_late: [RemoveUnnecessaryLate.new],
LinterLintCode.unnecessary_library_directive: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) 2025, 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 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:linter/src/lint_names.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'fix_processor.dart';

void main() {
defineReflectiveSuite(() {
defineReflectiveTests(RemoveUnnecessaryIgnoreTest);
});
}

// TODO(pq): add bulk fix tests
@reflectiveTest
class RemoveUnnecessaryIgnoreTest extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.REMOVE_IGNORED_DIAGNOSTIC;

@override
String get lintCode => LintNames.unnecessary_ignore;

Future<void> test_file_first() async {
await resolveTestCode('''
// ignore_for_file: unused_local_variable, return_of_invalid_type
int f() => null;
''');
await assertHasFix('''
// ignore_for_file: return_of_invalid_type
int f() => null;
''');
}

Future<void> test_file_last() async {
await resolveTestCode('''
// ignore_for_file: return_of_invalid_type, unused_local_variable
int f() => null;
''');
await assertHasFix('''
// ignore_for_file: return_of_invalid_type
int f() => null;
''');
}

Future<void> test_file_middle() async {
await resolveTestCode('''
// ignore_for_file: return_of_invalid_type, unused_local_variable, non_bool_negation_expression
int f() => !null;
''');
await assertHasFix('''
// ignore_for_file: return_of_invalid_type, non_bool_negation_expression
int f() => !null;
''');
}

Future<void> test_line_first() async {
await resolveTestCode('''
// ignore: unused_local_variable, return_of_invalid_type
int f() => null;
''');
await assertHasFix('''
// ignore: return_of_invalid_type
int f() => null;
''');
}

Future<void> test_line_last() async {
await resolveTestCode('''
// ignore: return_of_invalid_type, unused_local_variable
int f() => null;
''');
await assertHasFix('''
// ignore: return_of_invalid_type
int f() => null;
''');
}

Future<void> test_line_middle() async {
await resolveTestCode('''
// ignore: return_of_invalid_type, unused_local_variable, non_bool_negation_expression
int f() => !null;
''');
await assertHasFix('''
// ignore: return_of_invalid_type, non_bool_negation_expression
int f() => !null;
''');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ import 'remove_empty_else_test.dart' as remove_empty_else;
import 'remove_empty_statement_test.dart' as remove_empty_statement;
import 'remove_extends_clause_test.dart' as remove_extends_clause;
import 'remove_if_null_operator_test.dart' as remove_if_null_operator;
import 'remove_ignore_test.dart' as remove_ignore;
import 'remove_initializer_test.dart' as remove_initializer;
import 'remove_interpolation_braces_test.dart' as remove_interpolation_braces;
import 'remove_invocation_test.dart' as remove_invocation;
Expand Down Expand Up @@ -465,6 +466,7 @@ void main() {
remove_empty_statement.main();
remove_extends_clause.main();
remove_if_null_operator.main();
remove_ignore.main();
remove_initializer.main();
remove_interpolation_braces.main();
remove_invocation.main();
Expand Down
8 changes: 8 additions & 0 deletions pkg/analyzer/lib/src/dart/ast/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ extension IdentifierExtension on Identifier {
return _readElement(this);
}

Element2? get readElement2 {
return _readElement(this).asElement2;
}

SimpleIdentifier get simpleName {
var self = this;
if (self is SimpleIdentifier) {
Expand All @@ -233,6 +237,10 @@ extension IdentifierExtension on Identifier {
return _writeElement(this);
}

Element2? get writeElement2 {
return _writeElement(this).asElement2;
}

Element? get writeOrReadElement {
return _writeElement(this) ?? staticElement;
}
Expand Down
25 changes: 23 additions & 2 deletions pkg/analyzer/lib/src/dart/element/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,12 @@ class BindPatternVariableElementImpl2 extends PatternVariableElementImpl2
];
}

/// This flag is set to `true` if this variable clashes with another
/// pattern variable with the same name within the same pattern.
/// Whether this variable clashes with another pattern variable with the same
/// name within the same pattern.
bool get isDuplicate => _wrappedElement.isDuplicate;

/// Set whether this variable clashes with another pattern variable with the
/// same name within the same pattern.
set isDuplicate(bool value) => _wrappedElement.isDuplicate = value;

DeclaredVariablePatternImpl get node => _wrappedElement.node;
Expand Down Expand Up @@ -6793,6 +6797,23 @@ class JoinPatternVariableElementImpl2 extends PatternVariableElementImpl2
/// The identifiers that reference this element.
List<SimpleIdentifier> get references => _wrappedElement.references;

/// Returns this variable, and variables that join into it.
List<PatternVariableElementImpl2> get transitiveVariables {
var result = <PatternVariableElementImpl2>[];

void append(PatternVariableElementImpl2 variable) {
result.add(variable);
if (variable is JoinPatternVariableElementImpl2) {
for (var variable in variable.variables2) {
append(variable as PatternVariableElementImpl2);
}
}
}

append(this);
return result;
}

/// The variables that join into this variable.
List<PatternVariableElementImpl> get variables => _wrappedElement.variables;

Expand Down
34 changes: 25 additions & 9 deletions pkg/analyzer/lib/src/error/ignore_validator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,21 @@ class IgnoreValidator {
_reportUnignorableAndDuplicateIgnores(
unignorable, duplicated, ignoredOnLine);
}

// If there's more than one ignore, the fix is to remove the name.
// Otherwise, the entire comment can be removed.
var ignoredForFileCount = ignoredForFile.length;
var ignoredOnLineCount = 0;

//
// Remove all of the errors that are actually being ignored.
//
for (var error in _reportedErrors) {
var lineNumber = _lineInfo.getLocation(error.offset).lineNumber;
var ignoredOnLine = ignoredOnLineMap[lineNumber];
if (ignoredOnLine != null) {
ignoredOnLineCount += ignoredOnLine.length;
}

ignoredForFile.removeByName(error.ignoreName);
ignoredForFile.removeByName(error.ignoreUniqueName);
Expand All @@ -123,10 +132,15 @@ class IgnoreValidator {
//
// Report any remaining ignored names as being unnecessary.
//
_reportUnnecessaryOrRemovedOrDeprecatedIgnores(ignoredForFile,
forFile: true);
_reportUnnecessaryOrRemovedOrDeprecatedIgnores(
ignoredForFile,
ignoredForFileCount: ignoredForFileCount,
);
for (var ignoredOnLine in ignoredOnLineMap.values) {
_reportUnnecessaryOrRemovedOrDeprecatedIgnores(ignoredOnLine);
_reportUnnecessaryOrRemovedOrDeprecatedIgnores(
ignoredOnLine,
ignoredOnLineCount: ignoredOnLineCount,
);
}
}

Expand Down Expand Up @@ -172,7 +186,8 @@ class IgnoreValidator {
/// Report the [ignoredNames] as being unnecessary.
void _reportUnnecessaryOrRemovedOrDeprecatedIgnores(
List<IgnoredElement> ignoredNames,
{bool forFile = false}) {
{int? ignoredForFileCount,
int? ignoredOnLineCount}) {
if (!_validateUnnecessaryIgnores) return;

for (var ignoredName in ignoredNames) {
Expand Down Expand Up @@ -210,13 +225,14 @@ class IgnoreValidator {
}

late ErrorCode lintCode;
if (ignoredNames.length > 1) {
lintCode = forFile

if (ignoredForFileCount != null) {
lintCode = ignoredForFileCount > 1
? unnecessaryIgnoreNameFileLintCode
: unnecessaryIgnoreNameLocationLintCode;
: unnecessaryIgnoreFileLintCode;
} else {
lintCode = forFile
? unnecessaryIgnoreFileLintCode
lintCode = ignoredOnLineCount! > 1
? unnecessaryIgnoreNameLocationLintCode
: unnecessaryIgnoreLocationLintCode;
}

Expand Down
Loading

0 comments on commit ae8d812

Please sign in to comment.