Handle author and authors in a more sane way There is at least one published package with both author & authors set https://pub.dartlang.org/packages/crclib/versions/1.0.0 So we do normalization if both are set, eliminating duplicates and providing reasonable values from both author and authors properties Fixes https://github.com/dart-lang/pubspec_parse/issues/2
diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 6a5c3a6..90efa1c 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart
@@ -16,21 +16,24 @@ final String homepage; final String documentation; final String description; - final String author; + + /// If there is exactly 1 value in [authors], returns it. + /// + /// If there are 0 or more than 1, returns `null`. + @Deprecated( + 'Here for completeness, but not recommended. Use `authors` instead.') + String get author { + if (authors.length == 1) { + return authors.single; + } + return null; + } + final List<String> authors; @JsonKey(fromJson: _environmentMap) final Map<String, VersionConstraint> environment; - List<String> get allAuthors { - var values = <String>[]; - if (author != null) { - values.add(author); - } - values.addAll(authors); - return values; - } - @JsonKey(fromJson: _versionFromString) final Version version; @@ -43,19 +46,21 @@ @JsonKey(name: 'dependency_overrides', fromJson: _getDeps, nullable: false) final Map<String, Dependency> dependencyOverrides; + /// If [author] and [authors] are both provided, their values are combined + /// with duplicates eliminated. Pubspec( this.name, { this.version, - this.author, - this.environment, + String author, List<String> authors, + this.environment, this.homepage, this.documentation, this.description, Map<String, Dependency> dependencies, Map<String, Dependency> devDependencies, Map<String, Dependency> dependencyOverrides, - }) : this.authors = authors ?? const [], + }) : this.authors = _normalizeAuthors(author, authors), this.dependencies = dependencies ?? const {}, this.devDependencies = devDependencies ?? const {}, this.dependencyOverrides = dependencyOverrides ?? const {} { @@ -65,6 +70,17 @@ } factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); + + static List<String> _normalizeAuthors(String author, List<String> authors) { + var value = new Set<String>(); + if (author != null) { + value.add(author); + } + if (authors != null) { + value.addAll(authors); + } + return value.toList(); + } } // TODO: maybe move this to `dependencies.dart`?
diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index b98d766..4f040ff 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart
@@ -17,10 +17,10 @@ version: $checkedConvert(json, 'version', (v) => v == null ? null : _versionFromString(v as String)), author: $checkedConvert(json, 'author', (v) => v as String), - environment: $checkedConvert(json, 'environment', - (v) => v == null ? null : _environmentMap(v as Map)), authors: $checkedConvert(json, 'authors', (v) => (v as List)?.map((e) => e as String)?.toList()), + environment: $checkedConvert(json, 'environment', + (v) => v == null ? null : _environmentMap(v as Map)), homepage: $checkedConvert(json, 'homepage', (v) => v as String), documentation: $checkedConvert(json, 'documentation', (v) => v as String),
diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 7a4af76..bfe20f0 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart
@@ -10,38 +10,61 @@ test('trival', () { var value = parse({'name': 'sample'}); expect(value.name, 'sample'); + // ignore: deprecated_member_use + expect(value.author, isNull); expect(value.authors, isEmpty); expect(value.dependencies, isEmpty); }); - test('one author', () { - var value = parse({'name': 'sample', 'author': 'name@example.com'}); - expect(value.allAuthors, ['name@example.com']); - }); - - test('one author, via authors', () { - var value = parse({ - 'name': 'sample', - 'authors': ['name@example.com'] + group('author, authors', () { + test('one author', () { + var value = parse({'name': 'sample', 'author': 'name@example.com'}); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); }); - expect(value.authors, ['name@example.com']); - }); - test('many authors', () { - var value = parse({ - 'name': 'sample', - 'authors': ['name@example.com', 'name2@example.com'] + test('one author, via authors', () { + var value = parse({ + 'name': 'sample', + 'authors': ['name@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); }); - expect(value.authors, ['name@example.com', 'name2@example.com']); - }); - test('author and authors', () { - var value = parse({ - 'name': 'sample', - 'author': 'name@example.com', - 'authors': ['name2@example.com'] + test('many authors', () { + var value = parse({ + 'name': 'sample', + 'authors': ['name@example.com', 'name2@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, isNull); + expect(value.authors, ['name@example.com', 'name2@example.com']); }); - expect(value.allAuthors, ['name@example.com', 'name2@example.com']); + + test('author and authors', () { + var value = parse({ + 'name': 'sample', + 'author': 'name@example.com', + 'authors': ['name2@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, isNull); + expect(value.authors, ['name@example.com', 'name2@example.com']); + }); + + test('duplicate author values', () { + var value = parse({ + 'name': 'sample', + 'author': 'name@example.com', + 'authors': ['name@example.com', 'name@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); + }); }); group('invalid', () {