Skip to content

Commit

Permalink
Version 3.2.0-78.0.dev
Browse files Browse the repository at this point in the history
Merge eb54326 into dev
  • Loading branch information
Dart CI committed Aug 16, 2023
2 parents cc5eeac + eb54326 commit d6e1fca
Show file tree
Hide file tree
Showing 57 changed files with 1,143 additions and 460 deletions.
9 changes: 6 additions & 3 deletions pkg/analysis_server/lib/src/context_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -446,10 +446,13 @@ class ContextManagerImpl implements ContextManager {
var content = _readFile(path);
var node = loadYamlNode(content);
if (node is YamlMap) {
var validator = PubspecValidator(
resourceProvider, resourceProvider.getFile(path).createSource());
var lineInfo = LineInfo.fromContent(content);
var errors = validator.validate(node.nodes);
var errors = validatePubspec(
contents: node.nodes,
source: resourceProvider.getFile(path).createSource(),
provider: resourceProvider,
);

var converter = AnalyzerConverter();
convertedErrors = converter.convertAnalysisErrors(errors,
lineInfo: lineInfo, options: driver.analysisOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,11 @@ error.errorCode: ${error.errorCode}
if (yamlContent is! YamlMap) {
yamlContent = YamlMap();
}
var validator =
PubspecValidator(resourceProvider, pubspecFile.createSource());
var errors = validator.validate(yamlContent.nodes);
final errors = validatePubspec(
contents: yamlContent.nodes,
source: pubspecFile.createSource(),
provider: resourceProvider,
);
for (var error in errors) {
var generator =
PubspecFixGenerator(resourceProvider, error, content, document);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ class PubspecCodeActionsProducer extends AbstractCodeActionsProducer {
yamlContent = YamlMap();
}

final validator =
PubspecValidator(resourceProvider, pubspecFile.createSource());
final errors = validator.validate(yamlContent.nodes);
final errors = validatePubspec(
contents: yamlContent.nodes,
source: pubspecFile.createSource(),
provider: resourceProvider,
);

final codeActions = <CodeActionWithPriority>[];
for (final error in errors) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/protocol_server.dart' show SourceEdit;
import 'package:analysis_server/src/services/correction/fix/pubspec/fix_generator.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/pubspec/pubspec_validator.dart';
import 'package:analyzer/src/pubspec/pubspec_validator.dart'
as pubspec_validator;
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test/test.dart';
Expand Down Expand Up @@ -49,9 +50,11 @@ abstract class PubspecFixTest with ResourceProviderMixin {
if (yamlContent is! YamlMap) {
yamlContent = YamlMap();
}
var validator =
PubspecValidator(resourceProvider, pubspecFile.createSource());
var errors = validator.validate(yamlContent.nodes);
final errors = pubspec_validator.validatePubspec(
source: pubspecFile.createSource(),
contents: yamlContent.nodes,
provider: resourceProvider,
);
expect(errors.length, 1);
error = errors[0];
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/analyzer/doc/implementation/pub_diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ The basic recipe for implementing a new pubspec diagnostic is as follows:
3. Add corresponding tests to a new test library in
`test/src/pubspec/diagnostics`.
4. Implement analysis in a new validator in `lib/src/pubspec/validators` and
invoke it from PubspecValidator (or enhance an existing one).
add it to list of validators in `pubspec_validator.dart`
(or enhance an existing one).

Once implemented, you’ll want to look for ecosystem breakages. Useful bots to
watch:
Expand Down
140 changes: 77 additions & 63 deletions pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,52 @@ import 'package:analyzer/src/pubspec/validators/flutter_validator.dart';
import 'package:analyzer/src/pubspec/validators/name_validator.dart';
import 'package:analyzer/src/pubspec/validators/platforms_validator.dart';
import 'package:analyzer/src/pubspec/validators/screenshot_validator.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

class BasePubspecValidator {
/// The resource provider used to access the file system.
final ResourceProvider provider;

/// The source representing the file being validated.
final Source source;

BasePubspecValidator(this.provider, this.source);
/// List of [PubspecValidator] implementations.
const _pubspecValidators = <PubspecValidator>[
dependencyValidator,
fieldValidator,
flutterValidator,
nameValidator,
screenshotsValidator,
platformsValidator,
];

/// Validate pubspec with given [contents].
///
/// The [source] argument must be the source of the file being validated.
/// The [provider] argument must provide access to the file-system.
List<AnalysisError> validatePubspec({
// TODO(brianwilkerson) This method needs to take a `YamlDocument` rather
// than the contents of the document so that it can validate an empty file.
required Map<dynamic, YamlNode> contents,
required Source source,
required ResourceProvider provider,
}) {
final recorder = RecordingErrorListener();
final ctx = PubspecValidationContext._(
contents: contents,
source: source,
reporter: ErrorReporter(
recorder,
source,
isNonNullableByDefault: false,
),
provider: provider,
);

String? asString(dynamic node) {
if (node is String) {
return node;
}
if (node is YamlScalar && node.value is String) {
return node.value as String;
}
return null;
for (final validator in _pubspecValidators) {
validator(ctx);
}

/// Report an error for the given node.
void reportErrorForNode(
ErrorReporter reporter, YamlNode node, ErrorCode errorCode,
[List<Object>? arguments]) {
SourceSpan span = node.span;
reporter.reportErrorForOffset(
errorCode, span.start.offset, span.length, arguments);
}
return recorder.errors;
}

class PubspecField {
/// A function that can validate a `pubspec.yaml`.
typedef PubspecValidator = void Function(PubspecValidationContext ctx);

final class PubspecField {
/// The name of the sub-field (under `flutter`) whose value is a list of
/// assets available to Flutter apps at runtime.
static const String ASSETS_FIELD = 'assets';
Expand Down Expand Up @@ -81,48 +94,49 @@ class PubspecField {
static const String VERSION_FIELD = 'version';
}

class PubspecValidator {
/// The resource provider used to access the file system.
final ResourceProvider provider;
/// Context given to function that implement [PubspecValidator].
final class PubspecValidationContext {
/// Yaml document being validated
final Map<dynamic, YamlNode> contents;

/// The source representing the file being validated.
final Source source;

final DependencyValidator _dependencyValidator;
final FieldValidator _fieldValidator;
final FlutterValidator _flutterValidator;
final NameValidator _nameValidator;
final ScreenshotsValidator _screenshotsValidator;
final PlatformsValidator _platformsValidator;

/// Initialize a newly create validator to validate the content of the given
/// [source].
PubspecValidator(this.provider, this.source)
: _dependencyValidator = DependencyValidator(provider, source),
_fieldValidator = FieldValidator(provider, source),
_flutterValidator = FlutterValidator(provider, source),
_nameValidator = NameValidator(provider, source),
_screenshotsValidator = ScreenshotsValidator(provider, source),
_platformsValidator = PlatformsValidator(provider, source);

/// Validate the given [contents].
List<AnalysisError> validate(Map<dynamic, YamlNode> contents) {
// TODO(brianwilkerson) This method needs to take a `YamlDocument` rather
// than the contents of the document so that it can validate an empty file.
RecordingErrorListener recorder = RecordingErrorListener();
ErrorReporter reporter = ErrorReporter(
recorder,
source,
isNonNullableByDefault: false,
);
/// The reporter to which errors should be reported.
final ErrorReporter reporter;

_dependencyValidator.validate(reporter, contents);
_fieldValidator.validate(reporter, contents);
_flutterValidator.validate(reporter, contents);
_nameValidator.validate(reporter, contents);
_screenshotsValidator.validate(reporter, contents);
_platformsValidator.validate(reporter, contents);
/// The resource provider used to access the file system.
final ResourceProvider provider;

PubspecValidationContext._({
required this.contents,
required this.source,
required this.reporter,
required this.provider,
});

String? asString(dynamic node) {
if (node is String) {
return node;
}
if (node is YamlScalar && node.value is String) {
return node.value as String;
}
return null;
}

return recorder.errors;
/// Report an error for the given node.
void reportErrorForNode(
YamlNode node,
ErrorCode errorCode, [
List<Object>? arguments,
]) {
final span = node.span;
reporter.reportErrorForOffset(
errorCode,
span.start.offset,
span.length,
arguments,
);
}
}
Loading

0 comments on commit d6e1fca

Please sign in to comment.