diff --git a/.github/workflows/pr_validation.yaml b/.github/workflows/pr_validation.yaml index 85edfd5..da169fe 100644 --- a/.github/workflows/pr_validation.yaml +++ b/.github/workflows/pr_validation.yaml @@ -4,12 +4,10 @@ env: dart_version: 2.19.2 on: - push: - branches: - - main pull_request: branches: - main + - develop jobs: pr_validation: @@ -18,14 +16,33 @@ jobs: timeout-minutes: 15 steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - name: Dart install + uses: dart-lang/setup-dart@v1 with: sdk: ${{ env.dart_version }} - name: Pub Get run: dart pub get + - name: Validate Version Bump + run: dart run tool/validate_version_bump.dart + + - name: Format + run: dart format --set-exit-if-changed . + + - name: Run Tests + run: | + dart test --coverage=coverage + dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib + + - name: Verify Test Coverage + uses: VeryGoodOpenSource/very_good_coverage@v2 + with: + path: coverage/lcov.info + min_coverage: 70 + - name: Publish dry run run: dart pub publish --dry-run diff --git a/.github/workflows/upload_coverage.yaml b/.github/workflows/publish.yaml similarity index 80% rename from .github/workflows/upload_coverage.yaml rename to .github/workflows/publish.yaml index 83121b2..9009141 100644 --- a/.github/workflows/upload_coverage.yaml +++ b/.github/workflows/publish.yaml @@ -1,4 +1,4 @@ -name: Upload Coverage +name: Publish env: dart_version: 2.19.2 @@ -9,7 +9,7 @@ on: - main jobs: - coverage: + publish: runs-on: ubuntu-latest timeout-minutes: 15 @@ -25,7 +25,10 @@ jobs: - name: Run Tests run: | dart test --coverage=coverage - dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib + dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 + + - name: Publish to pub.dev + uses: dart pub publish diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d03590f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "[dart]": { + "editor.rulers": [ + 80, + ], + }, + "dart.lineLength": 80, +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f48619..d007363 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ -1. testing some changelog changes -2. changelog changes \ No newline at end of file +# 0.1.0 + +- initial release \ No newline at end of file diff --git a/CHANGELOG_BUBBLED.g.md b/CHANGELOG_BUBBLED.g.md index 697cfe0..c5e802d 100644 --- a/CHANGELOG_BUBBLED.g.md +++ b/CHANGELOG_BUBBLED.g.md @@ -1,2245 +1,13 @@ -# Bubbled Changelog - -## This app -changelog_bubbler | 0.1.0 -> 0.1.0 -
- CHANGELOG.md not found -
- - - -## Changed Dependencies - -
- pub.dev -
-
- get_it | 7.4.1 -> 7.6.0 | direct main -
- [7.6.0] - 09.05.2023 -* merged PR by lacopiroty https://github.com/fluttercommunity/get_it/pull/297 which now allows to access objects inside GetIt by runtime type too like -```Dart - getIt.registerSingleton(TestClass()); - - final instance1 = getIt.get(type: TestClass); - - expect(instance1 is TestClass, true); -``` -* fix for https://github.com/fluttercommunity/get_it/issues/299 -* fix for https://github.com/fluttercommunity/get_it/issues/300 - - -[7.5.0] - 07.05.2023 - -* new function `dropScope(scopeName)` which allows to remove and dispose any named scope even if it's not the top one. Great PR by @olexale https://github.com/fluttercommunity/get_it/pull/292 which fixes sort of race conditions if you create scopes just for the life time of a widget. -## [7.4.1] -* PR from @dzziwny which fixed an edge case with LazySingletons https://github.com/fluttercommunity/get_it/pull/284 -* Changed an assertion in case that an object is not registered to an Exception that also will throw in real time so that you get meaningful errors based on https://github.com/fluttercommunity/get_it/issues/312 - -## [7.4.0] -* `registerSingleton` now returns the passed instance as a return value thanks to the PR by @Rexios80 https://github.com/fluttercommunity/get_it/pull/242 -* In some cases GetIt will print error messages to the debug output. Now this won't happen anymore in release mode and can be completely disabled by setting `GetIt.noDebugOutput=true` following the PR from @James1345 -## [7.3.0] - -New features: -* `popScopeTil` got a new optional `inclusive` parameter so you can now decide if scope with the passed name should be popped too or only the ones above -* PR by @jtdLab that adds to reset a LazySingleton by providing an existing instance -* Fix for an internal state error by @ioantsaf -* Fix for a rare edge case if you manually `signalReady` -* Many PRs with improvements to spelling and grammar of readme, source documentation and even one assert message by @selcukguvel @isinghmitesh @UsamaKarim @nilsreichardt and Os-Prog -@Ae-Mc - - -## [7.2.0] - -* fix for https://github.com/fluttercommunity/get_it/issues/210 -* Parameters of factories are no longer needed to be casted because they are nullable -* downgraded the dependency on `async` to 2.6 again -* you couldn't push two Scopes without a name - -## [7.1.4] - -* fixed bug with manual synchronization of SingletonsWithDependencies -https://github.com/fluttercommunity/get_it/issues/196 - -## [7.1.3] - 07.05.2021 - -* Fix for https://github.com/fluttercommunity/get_it/issues/186 - -## [7.1.2] - 06.05.2021 - -* Thanks to the clever PR https://github.com/fluttercommunity/get_it/pull/185 by @kmartins `unregister` and `resetLazySingleton` now only have to be awaited if you use an async disposal function. - -## [7.1.1] - 05.05.2021 - -* `pushNewScope()` now got an optional `init` parameter where you can pass a function that registers new objects inside the newly pushed Scope. Doing the registration in this function ensures that the `onScopeChanged` call-back is called after the objects are registered. - -## [7.1.0] - 05.05.2021 - -* The new `Disposable` interface had a typo that now got corrected. You could call this a breaking change but as the last version change is just three days old I guess not many people will be affected by this correction. - -#### Getting notified when a scope change happens - -When using scopes with objects that shadow other objects its important to give the UI a chance to rebuild and acquire references to the now active objects. For this you can register an call-back function in GetIt -The getit_mixin has a matching `rebuiltOnScopeChange` method. - -```Dart - /// Optional call-back that will get call whenever a change in the current scope happens - /// This can be very helpful to update the UI in such a case to make sure it uses - /// the correct Objects after a scope change - void Function(bool pushed)? onScopeChanged; -``` -## [7.0.0] - 02.05.2021 - -This is a breaking change because there were some inconsistencies in the handling of the disposal functions that you can pass when registering an Object, pop a Scope or use `unregister()` `resetLazySingleton()`. Some of accepted a `FutureOr` method type, others just a `void` which meant you couldn't use async functions consistently. With this release you can use async functions in all disposal functions which unfortunately also required to change the signatures of the following functions: - -```dart - Future reset({bool dispose = true}); - - Future resetScope({bool dispose = true}); - - Future popScope(); - - Future popScopesTill(String name); - - FutureOr resetLazySingleton({ - Object? instance, - String? instanceName, - FutureOr Function(T)? disposingFunction, - }); - - FutureOr unregister({ - Object? instance, - String? instanceName, - FutureOr Function(T)? disposingFunction, - }); -``` - -Basically all functions that can possibly call a disposal functions should be awaited. -#### Implementing the `Disposable` interface - -Instead of passing a disposing function on registration or when pushing a Scope from V7.0 on your objects `onDispose()` method will be called -if the object that you register implements the `Disposable`´interface: - -```Dart -abstract class Disposable { - FutureOr onDispose(); -} -``` -#### Getting notified about the shadowing state of an object -In some cases it might be helpful to know if an Object gets shadowed by another one e.g. if it has some Stream subscriptions that it want to cancel before the shadowing object creates a new subscription. Also the other way round so that a shadowed Object gets notified when it's "active" again meaning when a shadowing object is removed. - -For this a class had to implement the `ShadowChangeHandlers` interface: - -```Dart -abstract class ShadowChangeHandlers { - void onGetShadowed(Object shadowing); - void onLeaveShadow(Object shadowing); -} -``` -When the Object is shadowed its `onGetShadowed()` method is called with the object that is shadowing it. When this object is removed from GetIt `onLeaveShadow()` will be called. - - - * Thanks to this PR https://github.com/fluttercommunity/get_it/pull/181 by @n3wtron you can now also make objects depend on other objects not only by type but also by type and name if you used a named registration - -## [6.1.1] - 13.04.2021 - -* small fix in getAsync with parameters - -## [6.1.0] - 12.04.2021 - -* Exceptions that occur during an async initialisation are now forwarded to the future that `allReady()` returns instead to get swallowed https://github.com/fluttercommunity/get_it/issues/148 -* Added a property `currentScopeName` to query the name of the currently active scope https://github.com/fluttercommunity/get_it/issues/153 -* `popScope` will know throw an Exception instead just an assert if you are already on the `baseScope` and you try to pop it. - -## [6.0.0] - 15.02.2021 - -* Official null safety release - -## [5.0.2] - 08.12.2020 - -* fixed https://github.com/fluttercommunity/get_it/issues/138 when calling `unRegister` the dispose function -that can be passed when registering wasn't called. - -## [5.0.1] - 23.09.2020 - -* fixed formatting in readme - -## [5.0.0-mixin-version] - 17.09.2020 - -* experimental - -## [5.0.0] - 15.09.2020 - -* New scope support for registration -* optional dispose functions for registered objects -* **Breaking change:** `reset()` now is async and returns a `Future` because it will call the new optional disposal functions that can be async -* **Breaking change:** If you use names to register your objects you now have to provide a type too or at least make sure the compiler can infer the type. With this change it is now possible to use the same name for different types. - -## [5.0.0-alpha] - 11.09.2020 - -* alpha version of V5.0 - -## [4.0.4] - 22.07.2020 - -* fixed linter errors - -## [4.0.3] - 22.07.2020 - -* fixes of several typos thanks to PRs from @Bryanx, @sspatari -* fixed error https://github.com/fluttercommunity/get_it/issues/92 - -## [4.0.2] - 26.04.2020 - -* removed too strong type check for passed factory parameter -* fixed error message https://github.com/fluttercommunity/get_it/issues/69 - - -## [4.0.1] - 19.03.2020 - -* overhauled readme -* removed unnecessary print statement - -## [4.0.0] - 26.02.2020 - -* Added abstract `WillSignalReady` class - -## [4.0.0-release-candidate] - 14.02.2020 - -* Breaking changes in API!!! -* Release candidate -* New Async functions -* Factories with parameters -* Improved startup synchronisation - -## [3.0.2] - 23.10.2019 - -* Bugfix when using named instances - -## [3.0.1] - 24.09.2019 - -* Bugfix with https://github.com/fluttercommunity/get_it/pull/21 - -## [3.0.0+1] - 07.09.2019 - -* Small fix to make the analyser happy - -## [3.0.0] - 07.09.2019 - -* Overhauled the signalling API because the way it was was not optimal. Now you can either signal globally or by passing the instance of the registered object that shall signal. This way it's ensured that you have to have access to the instance to signal, typically from within the instance with a `GetIt.instance.signalReady(this)` -individual signalling from other places but the instance itself is probably an error. -* Unregister of singletons /lazysingletons now possible also over a registered instance. -* Most asserts have bin replaced with throwing `Error`objects. -* The example now shows the ready signalling. - -## [2.1.0] - 26.08.2019 - -* Added handy ready signal to make start-up logic a bit easier -* Unregister of Objects now possible with optional disposing function - -## [2.0.3] - 26.08.2019 - -* Small fix - -## [2.0.2] - 19.08.2019 - -* Small fix - -## [2.0.1] - 19.08.2019 - -* Small fix - -## [2.0.0] - 18.08.2019 - -* **Breaking Change with V2.0.0** -you no longer can directly create instances of the type `GetIt` because `GetIt` is now a singleton please see [README](README.md) - -## [1.1.0] - 18.08.2019 - -* added named registration - -## [1.0.3+2] - 26.06.2019 - -* updated logo in readme - -## [1.0.3+1] - 22.05.2019 - -* updated authors - -## [1.0.3] - 01.03.2019 - -* Small fix so that intellisense works now if you use the short calling form without using `.get()` - -## [1.0.2] - 22.06.2018 - -* Moved package to [Flutter Community](https://github.com/fluttercommunity) - -## [1.0.1] - 20.06.2018 - -* Added `reset()`method - -## [1.0.0] - 22.05.2018 - -* Initial release - - -
- -
-process_run | ADDED | direct mainpubspec_lock_parse | ADDED | direct maincharcode | ADDED | transitive mainchecked_yaml | ADDED | transitive main
- collection | 1.17.1 -> 1.17.2 | direct main -
- ## 1.17.2 - -* Accept Dart SDK versions above 3.0. - -## 1.17.1 - -* Require Dart 2.18. -* Improve docs for `splitAfter` and `splitBefore`. - -## 1.17.0 - -* Add `Iterable.elementAtOrNull` and `List.elementAtOrNull` extension methods. -* Add a top-level `lastBy()` function that converts an `Iterable` to a `Map` by - grouping its elements using a function, keeping the last element for each - computed key. Also available as an extension method on `Iterable`. - -## 1.16.0 - -* Add an `Iterable.slices` extension method. -* Add `BoolList` class for space-efficient lists of boolean values. -* Use a stable sort algorithm in the `IterableExtension.sortedBy` method. -* Add `min`, `max`, `minOrNull` and `maxOrNull` getters to - `IterableDoubleExtension`, `IterableNumberExtension` and - `IterableIntegerExtension` -* Change `UnorderedIterableEquality` and `SetEquality` to implement `Equality` - with a non-nullable generic to allows assignment to variables with that type. - Assignment to `Equality` with a nullable type is still allowed because of - covariance. The `equals` and `hash` methods continue to accept nullable - arguments. -* Enable the `avoid_dynamic_calls` lint. - -## 1.15.0 - -* Stable release for null safety. - -## 1.15.0-nullsafety.5 - -* Fix typo in extension method `expandIndexed`. -* Update sdk constraints to `>=2.12.0-0 <3.0.0` based on beta release - guidelines. - -## 1.15.0-nullsafety.4 - -* Allow prerelease versions of the `2.12.x` sdk. - -* Remove the unusable setter `UnionSetController.set=`. This was mistakenly - added to the public API but could never be called. - -* Add extra optional `Random` argument to `shuffle`. - -* Add a large number of extension methods on `Iterable` and `List` types, - and on a few other types. - These either provide easy access to the operations from `algorithms.dart`, - or provide convenience variants of existing `Iterable` and `List` methods - like `singleWhereOrNull` or `forEachIndexed`. - -## 1.15.0-nullsafety.3 - -* Allow 2.10 stable and 2.11.0 dev SDK versions. -* Add `toUnorderedList` method on `PriorityQueue`. -* Make `HeapPriorityQueue`'s `remove` and `contains` methods - use `==` for equality checks. - Previously used `comparison(a, b) == 0` as criteria, but it's possible - to have multiple elements with the same priority in a queue, so that - could remove the wrong element. - Still requires that objects that are `==` also have the same priority. - -## 1.15.0-nullsafety.2 - -Update for the 2.10 dev sdk. - -## 1.15.0-nullsafety.1 - -* Allow the <=2.9.10 stable sdks. - -## 1.15.0-nullsafety - -Pre-release for the null safety migration of this package. - -Note that `1.15.0` may not be the final stable null safety release version, -we reserve the right to release it as a `2.0.0` breaking change. - -This release will be pinned to only allow pre-release sdk versions starting -from `2.9.0-dev.18.0`, which is the first version where this package will -appear in the null safety allow list. - -## 1.14.13 - -* Deprecate `mapMap`. The Map interface has a `map` call and map literals can - use for-loop elements which supersede this method. - -## 1.14.12 - -* Fix `CombinedMapView.keys`, `CombinedMapView.length`, - `CombinedMapView.forEach`, and `CombinedMapView.values` to work as specified - and not repeat duplicate items from the maps. - * As a result of this fix the `length` getter now must iterate all maps in - order to remove duplicates and return an accurate length, so it is no - longer `O(maps)`. - -## 1.14.11 - -* Set max SDK version to `<3.0.0`. - -## 1.14.10 - -* Fix the parameter names in overridden methods to match the source. -* Make tests Dart 2 type-safe. -* Stop depending on SDK `retype` and deprecate methods. - -## 1.14.9 - -* Fixed bugs where `QueueList`, `MapKeySet`, and `MapValueSet` did not adhere to - the contract laid out by `List.cast`, `Set.cast` and `Map.cast` respectively. - The returned instances of these methods now correctly forward to the existing - instance instead of always creating a new copy. - -## 1.14.8 - -* Deprecated `Delegating{Name}.typed` static methods in favor of the new Dart 2 - `cast` methods. For example, `DelegatingList.typed(list)` can now be - written as `list.cast()`. - -## 1.14.7 - -* Only the Dart 2 dev SDK (`>=2.0.0-dev.22.0`) is now supported. -* Added support for all Dart 2 SDK methods that threw `UnimplementedError`. - -## 1.14.6 - -* Make `DefaultEquality`'s `equals()` and `hash()` methods take any `Object` - rather than objects of type `E`. This makes `const DefaultEquality()` - usable as `Equality` for any `E`, which means it can be used in a const - context which expects `Equality`. - - This makes the default arguments of various other const equality constructors - work in strong mode. - -## 1.14.5 - -* Fix issue with `EmptyUnmodifiableSet`'s stubs that were introduced in 1.14.4. - -## 1.14.4 - -* Add implementation stubs of upcoming Dart 2.0 core library methods, namely - new methods for classes that implement `Iterable`, `List`, `Map`, `Queue`, - and `Set`. - -## 1.14.3 - -* Fix `MapKeySet.lookup` to be a valid override in strong mode. - -## 1.14.2 - -* Add type arguments to `SyntheticInvocation`. - -## 1.14.1 - -* Make `Equality` implementations accept `null` as argument to `hash`. - -## 1.14.0 - -* Add `CombinedListView`, a view of several lists concatenated together. -* Add `CombinedIterableView`, a view of several iterables concatenated together. -* Add `CombinedMapView`, a view of several maps concatenated together. - -## 1.13.0 - -* Add `EqualityBy` - -## 1.12.0 - -* Add `CaseInsensitiveEquality`. - -* Fix bug in `equalsIgnoreAsciiCase`. - -## 1.11.0 - -* Add `EqualityMap` and `EqualitySet` classes which use `Equality` objects for - key and element equality, respectively. - -## 1.10.1 - -* `Set.difference` now takes a `Set` as argument. - -## 1.9.1 - -* Fix some documentation bugs. - -## 1.9.0 - -* Add a top-level `stronglyConnectedComponents()` function that returns the - strongly connected components in a directed graph. - -## 1.8.0 - -* Add a top-level `mapMap()` function that works like `Iterable.map()` on a - `Map`. - -* Add a top-level `mergeMaps()` function that creates a new map with the - combined contents of two existing maps. - -* Add a top-level `groupBy()` function that converts an `Iterable` to a `Map` by - grouping its elements using a function. - -* Add top-level `minBy()` and `maxBy()` functions that return the minimum and - maximum values in an `Iterable`, respectively, ordered by a derived value. - -* Add a top-level `transitiveClosure()` function that returns the transitive - closure of a directed graph. - -## 1.7.0 - -* Add a `const UnmodifiableSetView.empty()` constructor. - -## 1.6.0 - -* Add a `UnionSet` class that provides a view of the union of a set of sets. - -* Add a `UnionSetController` class that provides a convenient way to manage the - contents of a `UnionSet`. - -* Fix another incorrectly-declared generic type. - -## 1.5.1 - -* Fix an incorrectly-declared generic type. - -## 1.5.0 - -* Add `DelegatingIterable.typed()`, `DelegatingList.typed()`, - `DelegatingSet.typed()`, `DelegatingMap.typed()`, and - `DelegatingQueue.typed()` static methods. These wrap untyped instances of - these classes with the correct type parameter, and assert the types of values - as they're accessed. - -* Fix the types for `binarySearch()` and `lowerBound()` so they no longer - require all arguments to be comparable. - -* Add generic annotations to `insertionSort()` and `mergeSort()`. - -## 1.4.1 - -* Fix all strong mode warnings. - -## 1.4.0 - -* Add a `new PriorityQueue()` constructor that forwards to `new - HeapPriorityQueue()`. - -* Deprecate top-level libraries other than `package:collection/collection.dart`, - which exports these libraries' interfaces. - -## 1.3.0 - -* Add `lowerBound` to binary search for values that might not be present. - -* Verify that the is valid for `CanonicalMap.[]`. - -## 1.2.0 - -* Add string comparators that ignore ASCII case and sort numbers numerically. - -## 1.1.3 - -* Fix type inconsistencies with `Map` and `Set`. - -## 1.1.2 - -* Export `UnmodifiableMapView` from the Dart core libraries. - -## 1.1.1 - -* Bug-fix for signatures of `isValidKey` arguments of `CanonicalizedMap`. - -## 1.1.0 - -* Add a `QueueList` class that implements both `Queue` and `List`. - -## 0.9.4 - -* Add a `CanonicalizedMap` class that canonicalizes its keys to provide a custom - equality relation. - -## 0.9.3+1 - -* Fix all analyzer hints. - -## 0.9.3 - -* Add a `MapKeySet` class that exposes an unmodifiable `Set` view of a `Map`'s - keys. - -* Add a `MapValueSet` class that takes a function from values to keys and uses - it to expose a `Set` view of a `Map`'s values. - - - - -json_annotation | ADDED | transitive mainsynchronized | ADDED | transitive mainmocktail | ADDED | direct dev
- _fe_analyzer_shared | 59.0.0 -> 60.0.0 | transitive dev -
- CHANGELOG.md not found -
- -
-
- analyzer | 5.11.1 -> 5.12.0 | transitive dev -
- ## 5.12.0 -* Deprecated `DartType.isDynamic`, use `is DynamicType` instead. -* Updated `NamedType` to use `importPrefix` and `name2` token. - The deprecated `name` node is still visited in this version, but will stop - in the next major version. -* Updated `ExtensionOverride` to use `importPrefix` and `name` token. - The deprecated `extensionName` node is still visited in this version, but - will stop in the next major version. -* Deprecated the default `AnalysisError` constructor, use `tmp` constructor, - with names formal parameters. Theoretically no clients should use either, - but practically there are two uses currently. -* Added `InvalidType`, used when a named type cannot be resolved, or a - property cannot be resolved, etc. Previously `DynamicType` was used. - In the future `DynamicType` will be used only when specified explicitly, - or a property is resolved against a dynamic target. The clients should - prepare by checking also for `InvalidType` in addition to `DynamicType`. - -## 5.11.1 -* Restore previously published `finalKeyword`, `interfaceKeyword` and - `sealedKeyword` of `MixinElement`. We added them preliminary while - working on the class modifiers feature, but eventually decided to remove. - See https://github.com/dart-lang/sdk/issues/52159 for details. - -## 5.11.0 -* Removed `@experimental` from AST nodes and elements for records and patterns. -* Deprecated `IfStatement.condition`, use `expression` instead. -* Added `NamedType.importPrefix`, `NamedType.name2`, and `NamedType.element`. - Deprecated `NamedType.name`. Currently `Identifier` is an expression, and - an expression as a name of a type does not make sense. So, instead we model - it as a name token, the `Element` that it references, and an optional import - library prefix reference. - -## 5.10.0 -* Added `DartType.isDartCoreType`. - -## 5.9.0 -* Deprecated `FunctionBody.isPotentiallyMutatedInClosure`, not used by clients. -* Fix for `FunctionBody.isPotentiallyMutatedInScope` and pattern assignment. - -## 5.8.0 -* Deprecated `DartType.isVoid`, use `is VoidType` instead. -* `records`, `patterns`, and `class-modifiers` features enabled by default. - -## 5.7.1 -* Require SDK `>=2.19.0 <3.0.0` to use `PathNotFoundException` from `dart:io`. - -## 5.7.0 -* Work on `class-modifiers` feature. -* Work on `patterns` feature. -* Support for primitive equality. - -## 5.6.0 -* Fixes for patterns parsing. -* Implemented `DartPattern.precedence`. - -## 5.5.0 -* Rename `RecordPatternField` to `PatternField`. -* Rename `RecordPatternFieldName` to `PatternFieldName`. - -## 5.4.0 -* Bug fixes: 50660 - -## 5.3.1 -* Require `collection: ^1.17.0` because we use `elementAtOrNull`. - -## 5.3.0 -* Use `3.0.0` as the current language version. - -## 5.2.0 -* Deprecated `Element.enclosingElement3`, use `enclosingElement` instead. -* Deprecated `Directive.element2`, use `element` instead. -* Deprecated `CatchClause.exceptionParameter2`, use `exceptionParameter` instead. -* Deprecated `CatchClause.stackTraceParameter2`, use `stackTraceParameter` instead. -* Deprecated `DartType.element2`, use `element` instead. -* Deprecated `Element.isAccessibleIn2()`, use `isAccessibleIn()` instead. -* Deprecated `CompilationUnitElement.enums2`, use `enums` instead. -* Deprecated `CompilationUnitElement.getEnum2()`, use `getEnum()` instead. -* Deprecated `CompilationUnitElement.mixins2`, use `mixins` instead. -* Deprecated `LibraryElement.parts2`, use `parts` instead. -* Deprecated `ImportElement.imports2`, use `imports` instead. -* Add `AnalysisDriverForPackageBuild.sdkLibraryUris`. -* Deprecated `buildSdkSummary2()`, use `buildSdkSummary()` instead. - -## 5.1.0 -* Deprecated `AstNode.name2`, use `name` instead. -* Deprecated `AstNode.declaredElement2`, use `declaredElement` instead. - -## 5.0.0 -* Removed deprecated methods from AST. -* Removed deprecated `DiagnosticMessage.message`. -* Removed deprecated `LibraryElement.getImportsWithPrefix()`. -* Removed deprecated `ParameterElement.isNotOptional`. -* Removed deprecated `DartType.displayName`. -* Removed deprecated methods from `AnalysisDriver`. -* Removed deprecated `ClassOrMixinDeclaration`. -* Removed deprecated `Declaration.declaredElement`. -* Removed deprecated `Element.enclosingElement` and `enclosingElement2`. -* Removed deprecated `ExportElement`, `ImportElement`. -* Removed deprecated `NamedCompilationUnitMember.name`. -* Removed deprecated `Declaration.declaredElement`. -* Removed deprecated `DartType.element`. - -## 4.7.0 -* Add missing `addXyz` to `NodeLintRegistry`. -* Add `lookUpInheritedConcreteX()` to `InterfaceElement`. - -## 4.6.0 -* Added `DartType.element2`, so that `InterfaceType.element2` overrides it. - -## 4.5.0 -* Update deprecation message for `FormalParameter.identifier`. -* Deprecated `ClassOrMixinDeclaration`, use `ClassDeclaration` and `MixinDeclaration` directly. -* Deprecated `Declaration.declaredElement`, use `declaredElement2` instead. - This is necessary to separate `ClassElement`, `EnumElement`, and `MixinElement`. - And, in the future, augmentations like `ClassAugmentationElement`, etc. -* Deprecated `TypeSystem.instantiateToBounds2()`, use `instantiateInterfaceToBounds()` or - `instantiateTypeAliasToBounds()` instead. - -## 4.4.0 -* Deprecated `ClassDeclaration.isAbstract`, use `abstractKeyword` instead. -* Deprecated `ClassTypeAlias.isAbstract`, use `abstractKeyword` instead. -* Deprecated `ClassOrMixinDeclaration.getField`, filter `members` instead. -* Deprecated `ClassOrMixinDeclaration.getMethod`, filter `members` instead. -* Deprecated `ClassDeclaration.getConstructor`, filter `members` instead. -* Deprecated `Directive.element`, use `element2` instead. -* Deprecated `ClassElement.hasStaticMember`, it is not useful for clients. -* Deprecated `NamespaceDirective.uriElement`, use `element2.uri` with `DirectiveUriWithLibrary` instead. -* Deprecated `UriBasedDirective.uriContent`, `UriBasedDirective.uriElement`, `UriBasedDirective.uriSource`. - Use `Directive.element2.uri` instead. -* Deprecated `NamespaceDirective.selectedSource`, use `element2.uri` with `DirectiveUriWithSource` instead. -* Deprecated `Configuration.uriSource`, use `resolvedUri` instead. -* Deprecated `CatchClause.exceptionParameter` and `CatchClause.stackTraceParameter`. - Use `exceptionParameter2` and `stackTraceParameter2` instead. -* Added `FileResult.isAugmentation` and `isLibrary` to complement `isPart`. -* Deprecated 'XyzDeclaration.name' in AST, use `name2` and `declaredElement` instead. -* Deprecated `Element.enclosingElement2`, use `enclosingElement3` instead. The meaningful change is that - `ConstructorElement.enclosingElement3` returns now `InterfaceElement`, not `ClassElement`. -* Deprecated `get enums/mixin`, use `get enums2/mixins2` instead. -* Deprecated `DartType.element`, check for `InterfaceType`, `TypeParameterType`, and then ask the element. -* Deprecated `ClassElement.isEnum` and `isMixin`. Check for `is EnumElement` and `is MixinElement` instead. -* Deprecated `LibraryElement.getType()` use `getClass()` instead. - -## 4.3.1 -* Fix `identifier` for `LibraryExportElement` and `LibraryImportElement`. - -## 4.3.0 -* Deprecated `Directive.keyword`, use corresponding `xyzToken` in specific directives. -* Deprecated `LibraryElement.parts`, use `parts2` instead. -* Deprecated `LibraryElement.exports`, use `libraryExports` instead. -* Deprecated `LibraryElement.imports`, use `libraryImports` instead. -* Deprecated `Element.enclosingElement`, use `enclosingElement2` instead. -* `Member` is not equal to `ElementImpl`, use `Element.declaration`. - -## 4.2.0 -* Update SDK constraints to `>=2.17.0 <3.0.0`. -* Deprecated `ImportDirective.COMPARATOR`, use appropriate custom logic, if necessary. -* Deprecated `Element.isAccessibleIn()`, use `isAccessibleIn2()` instead. -* Bug fixes: 49225. - -## 4.1.0 -* Deprecated `ParameterElement.isNotOptional`, use `isRequired` instead. -* Deprecated `ResourceProviderMixin.newFile2`, use `newFile` instead. -* Deprecated `ResourceProviderMixin.newAnalysisOptionsYamlFile2`, use `newAnalysisOptionsYamlFile` instead. -* Deprecated `DartType.resolveToBound`, use `TypeSystem.resolveToBound` instead. -* Deprecated `LibraryElement.getImportsWithPrefix`, use `PrefixElement.imports` instead. -* Fix for `AnalysisSession.getFile()` to return updated content after `applyPendingFileChanges`. - -## 4.0.0 -* Removed deprecated `UriKind` and `Source.uriKind`. -* Removed deprecated `LibraryElement.hasExtUri`. -* Removed deprecated `LibraryElement.hasLoadLibraryFunction`. -* Removed deprecated `ImportElement.prefixOffset`. -* Removed deprecated `CompilationUnitElement.types`. -* Removed deprecated `Source.encoding`. -* Removed deprecated `Source.isInSystemLibrary`. -* Removed deprecated `Source.modificationStamp`. -* Removed deprecated `stamp` in `MemoryResourceProvider`. -* Removed deprecated `SourceFactory.restoreUri`, use `pathToUri` instead. -* Removed deprecated `AnalysisContext.workspace`. -* The `isNonNullableByDefault` parameter in `ErrorReporter` is now required. -* Removed `Element.SORT_BY_OFFSET`, it is not used. -* Changed synchronous `AnalysisSession.getFile` and `getParsedUnit` to fail - if there are pending file changes, instead of reading. As for any other - `AnalysisSession` method, await `AnalysisContext.applyPendingFileChanges()`. -* Removed `Token.copy()` and `copyComments()`. -* Removed `CommentToken.remove()`. -* Removed deprecated `astFactory` and `AstFactory`. -* Removed `AnalysisOptions.signature` and `signaturesEqual`. -* Removed deprecated `buildSdkSummary()`. - -## 3.4.1 -* Remove checks for consistency after operations in `AnalysisSession`. - -## 3.4.0 -* Deprecated `Resource.parent2`, use `parent` instead. -* Deprecated `astFactory`, clients should not create AST nodes manually. -* Changed `CompilationUnit.lineInfo` to be non-nullable. -* Changed `CompilationUnitElement.lineInfo` to be non-nullable. -* Deprecated `ResourceProviderMixin.newFile`, use `newFile2` instead. -* Deprecated `ResourceProviderMixin.newAnalysisOptionsYamlFile`. -* Added `AnalysisContext.changeFile` and `AnalysisContext.applyPendingFileChanges`. -* Deprecated `buildSdkSummary`, use asynchronous `buildSdkSummary2` instead. - -## 3.3.1 -* Report HintCode.OVERRIDE_ON_NON_OVERRIDING_xyz on enum. - -## 3.3.0 -* Added `getField` to `ExtensionElement`. -* Added `isGenerative` to `ConstructorElement`. -* Added `isDartCoreEnum` to `ClassElement` and `DartType`. -* Deprecated `superclass2`, `mixinTypes2`, etc. Use `superclass`, `mixinTypes`, etc. -* APIs for `enhanced-enums` language feature. - -## 3.2.0 -* Deprecated `changes` getter in `File` and `Folder`, use `watch()` instead. - -## 3.1.0 -* New internal API for `package:dart_style`. -* Removed deprecated non-API `MockSdk` class. -* Removed deprecated `AnalysisDriver` constructor. -* Updated the current language version to `2.17`. - -## 3.0.0 -* Removed deprecated `DartType.aliasElement/aliasArguments`. -* Removed deprecated constructors from `FeatureSet`. -* Removed `UnitElementResult.signature` - unused by clients. -* Removed deprecated `AnalysisError.withNamedArguments`. -* Removed deprecated `ErrorReporter.reportErrorMessage`. -* Removed deprecated `ResourceProvider.getModificationTimes()`. -* Removed deprecated `MemoryResourceProvider.newDummyLink()`. -* Removed deprecated `MemoryResourceProvider.updateFile()`. -* Removed deprecated `Resource.parent`. -* Removed deprecated `ResultState` and `AnalysisResult.state`. -* Removed deprecated `summary_file_builder` library. -* Removed deprecated `message` and `correction` from `ErrorCode`. -* Removed deprecated `lookUp` methods from `InterfaceType`. -* Removed deprecated `InterfaceType.getSmartLeastUpperBound`. -* Removed deprecated `path` and `uri` from `AnalysisResult`. -* Removed deprecated methods from `AnalysisSession`. -* Removed `TypeName` and corresponding methods. -* Removed deprecated methods from `TypeProvider`. - -## 2.8.0 -* Deprecations and renames for `getXyz` methods in `AnalysisDriver`. -* Removed uppercase named constants from `double` in mock SDK. -* Deprecated `path` and `uri` from `AnalysisResult`. -* Deprecated `UriResolver.restoreAbsolute`, use `pathToUri` instead. -* Deprecated `SourceFactory.restoreAbsolute`, use `pathToUri` instead. -* Deprecated `UriKind` and `Source.uriKind`. -* Deprecated `Source.modificationStamp`. -* Deprecated `Source.isInSystemLibrary`, use `uri.isScheme('dart')` instead. -* Fixed #47715. - -## 2.7.0 -* Updated `ConstructorElement.displayName` to either `Class` or `Class.constructor`. -* Deprecated `InterfaceType.getSmartLeastUpperBound`, use `TypeSystem.leastUpperBound` instead. -* Deprecated `MockSdk`, use `createMockSdk` and `FolderBasedDartSdk` instead. - -## 2.6.0 -* Deprecated `AnalysisResult.state`, check for specific valid or invalid subtypes. -* Deprecated `ResultState`. -* Deprecated `LibraryElement.hasExtUri`, FFI should be used instead. - -## 2.5.0 -* Updated `MockSdk` to include more declarations. - -## 2.4.0 -* Deprecated `ResourceProvider.getModificationTimes()`. -* Deprecated `MemoryResourceProvider.newDummyLink()`. -* Deprecated `MemoryResourceProvider.updateFile()`. -* Deprecated `TypeName`, use `NamedType` instead. -* Override `AstVisitor.visitNamedType()` instead of `visitTypeName()`. -* Deprecated `ClassTypeAlias.superclass`, use `superclass2` instead. -* Deprecated `ConstructorName.type`, use `type2` instead. -* Deprecated `ExtendsClause.superclass`, use `superclass2` instead. -* Deprecated `ImplementsClause.interfaces`, use `interfaces2` instead. -* Deprecated `OnClause.superclassConstraints`, use `superclassConstraints2` instead. -* Deprecated `TypeLiteral.typeName`, use `type` instead. -* Deprecated `WithClause.mixinTypes`, use `mixinTypes2` instead. -* Deprecated `AstFactory.typeName()`, use `namedType()` instead. - -## 2.3.0 -* Enable `constructor-tearoffs` feature by default in `2.15`. -* Improvements in constructors tear-off implementation. - -## 2.2.0 -* Improvements in constructors tear-off implementation. - -## 2.1.0 -* Changed `AnalysisResult.path` to be non-nullable. -* Changed `ParsedLibraryResult.units` to be non-nullable. -* Changed `ResolvedLibraryResult.element` to be non-nullable. -* Changed `ResolvedLibraryResult.units` to be non-nullable. -* Changed `ResolvedUnitResult.content` to be non-nullable. -* Changed `ResolvedUnitResult.unit` to be non-nullable. -* Deprecated and renamed `AnalysisSession.getXyz2()` into `getXyz()`. -* Changed `AnalysisDriver.results` to `Stream`. - It used to always produce `ResolvedUnitResult`s, but sometimes its - `content` and `unit` were `null`, when the result actually had only errors. - Now it produces either `ResolvedUnitResult`, or `ErrorsResult`, or - some other results that might be added in the future. -* Added `DartType.alias` with information about instantiated type alias. - The type alias element and arguments are present or absent together. -* Deprecated `DartType.aliasElement` and `DartType.aliasArguments`. -* Updated the current language version to `2.15`. - -## 2.0.0 -* Removed deprecated `Scope.lookup2()`. -* Removed deprecated setters in API of AST. -* Removed deprecated `FunctionTypeAliasElement`. -* Updated `LineInfo.getLocation()` to return `CharacterLocation`. -* Removed deprecated `LineInfo_Location`. -* Removed deprecated methods from `AnalysisSession`. -* Changed `DartObject.type` from `ParameterizedType?` to `DartType?`. -* Changed `FunctionType` to implement `DartType`, not `ParameterizedType`. -* Removed `FunctionType.element` and `FunctionType.typeArguments`. -* Changed `DartObject.type` from `ParameterizedType?` to `DartType?`. -* Changed `FunctionType` to implement `DartType`, not `ParameterizedType`. -* Removed `FunctionType.element` and `FunctionType.typeArguments`. -* Added `StringInterpolation.firstString` and `lastString`, to express - explicitly that there are always (possibly empty) strings as the first - and the last elements of an interpolation. -* Deprecated `ImportElement.prefixOffset`, use `prefix.nameOffset` instead. -* Deprecated `CompilationUnitElement.types`, use `classes` instead. -* Added `Element.nonSynthetic`, use it to get the element that caused creation - of this element, e.g. the field for a synthetic getter. -* `FieldElement.isFinal` is `true` only when the field is not synthetic. -* Synthetic getters and setters now use `-1` as `nameOffset`. -* Fixed bug that `defaultValueCode` is `null` for field formal parameters. -* Updated `LibraryElement.name` so that it is non-nullable. - -## 1.7.0 -* Require `meta: ^1.4.0`. - -## 1.6.0 -* Deprecated `AnalysisDriver` default constructor. Added `tmp1`. The goal - is to allow deprecating and removing unused parameters. -* Added AST structures and visit methods to support the upcoming "constructor - tearoffs" feature: `ConstructorReference`, `FunctionReference`, and - `TypeLiteral`. - -## 1.5.0 -* Support for the language version `2.14`. -* Deprecated `AnalysisSession.getUnitElement()`. - Use `AnalysisSession.getUnitElement2()` instead. -* Deprecated `AnalysisSession.getResolvedUnit()`. - Use `AnalysisSession.getResolvedUnit2()` instead. -* Deprecated `AnalysisSession.getResolvedLibrary()`. - Use `AnalysisSession.getResolvedLibrary2()` instead. -* Deprecated `AnalysisSession.getResolvedLibraryByElement()`. - Use `AnalysisSession.getResolvedLibraryByElement2()` instead. -* Deprecated `AnalysisSession.getLibraryByUri()`. - Use `AnalysisSession.getLibraryByUri2()` instead. -* Deprecated `AnalysisSession.getErrors()`. - Use `AnalysisSession.getErrors2()` instead. -* Deprecated `AnalysisSession.getParsedLibrary()`. - Use `AnalysisSession.getParsedLibrary2()` instead. -* Deprecated `AnalysisSession.getParsedLibraryByElement()`. - Use `AnalysisSession.getParsedLibraryByElement2()` instead. -* Deprecated `AnalysisSession.getParsedUnit()`. - Use `AnalysisSession.getParsedUnit2()` instead. -* Deprecated `AnalysisSession.getFile()` and `getSourceKind()`. - Use `AnalysisSession.getFile2()` instead. -* Deprecated `AnalysisSession.getUnitElementSignature()`. - This method is not used by any known client, and will be removed. - -## 1.4.0 -* Deprecated `TypeProvider.nonSubtypableClasses`. - Use `TypeProvider.isNonSubtypableClass` instead. -* Added `sdkPath` to `AnalysisContextCollection` constructor. -* Improved support for generalized type aliases. -* The feature `nonfunction-type-aliases` is enabled by default in the - language version `2.13`. - -## 1.3.0 -* Added `Expression.inConstantContext` to API. -* Updated documentation comments for some getters that don't return `null`. -* Fixed an issue with accessing `CompilationUnitElement.mixins` before `types`. -* Implemented metadata resolution with type arguments and inference. -* Fixed issue with metadata on enum constants. - -## 1.2.0 -* Deprecated all setters in API of AST. Use `parseString()` instead. -* `AnalysisSession.getErrors()` does not return `null`, check its `state`. -* Support for `aliasElement` and `aliasArguments` for aliases of - `InterfaceType`s and `TypeParameterType`s. - -## 1.1.0 -* Deprecated `TypeProvider.futureType2()`, `iterableType2()`, etc. - Use corresponding `TypeProvider.futureType()`, `iterableType()`, etc. -* Remove experimental markers from Null Safety APIs. -* Added `Resource.parent2` and deprecated `Resource.parent`. -* Added `Folder.isRoot`. -* Added `FolderExtension` with `withAncestors`. -* Added `ContextRoot.workspace`, deprecated `AnalysisContext.workspace`. -* Deprecated `ElementVisitor.visitFunctionTypeAliasElement()`. - Override `ElementVisitor.visitTypeAliasElement()` instead. -* Deprecated `FunctionTypeAliasElement`. Use `TypeAliasElement` instead. - -## 1.0.0 -* Stable null safety release. -* Updated dependencies to null safe releases. - -## 0.42.0-nullsafety.0 -* Migrated to null safety, min SDK is `2.12.0`. -* Deprecated `FunctionTypeAliasElement.function`. - Use `TypeAliasElement.aliasedElement` instead. -* Widened the dependency on package:crypto to include version 3.0.0. -* Deprecated `CompilationUnitElement.functionTypeAliases`. - Use `CompilationUnitElement.typeAliases` instead. -* Added `AnalysisContext.sdkRoot`. -* Removed `NullSafetyUnderstandingFlag`. -* Removed `functionTypeAliasElement` from `TypeSystem.instantiateToBounds2`. -* Added `Annotation.typeArguments` in preparation for supporting #44838. -* Removed `actualUri` from `UriResolver.resolveAbsolute`. -* Deprecated `FunctionType.element` and `FunctionType.typeArguments`. - -## 0.41.1 -* Updated `PackageBuildWorkspace` that supports `package:build` to stop - at the first directory with `pubspec.yaml`, and don't try to go up - and find another one with both `pubspec.yaml` and `.dart_tool/build`. -* Added a new constructor for non-API `ErrorCode` class. It will be used to - migrate existing `ErrorCode` subclasses, and then deprecated and removed. - -## 0.41.0 -* Replaced `Scope.lookup({id, setter})` with `lookup(id)`. -* Deprecated `Scope.lookup2(id)`, use `lookup()` instead. -* Removed deprecated `Member.baseElement`. -* Removed deprecated `package:analyzer/analyzer.dart` library. -* Removed deprecated `ElementAnnotation.constantValue`. -* Removed deprecated `VariableElement.constantValue`. -* Removed deprecated `VariableElement.initializer`. -* Removed deprecated `auxiliaryElements`. -* The value of`FunctionType.element` for types created from a `typedef` - is now `FunctionTypeAliasElement`, not its function element. -* Removed deprecated `GenericTypeAliasElement`. -* Removed `PhysicalResourceProvider.NORMALIZE_EOL_ALWAYS`. -* Changed the default `PhysicalResourceProvider` constructor to no longer take a - required positional parameter (removed the existing `fileReadMode` positional - parameter). - -## 0.40.6 -* The non_nullable feature is released in 2.12 language version. -* Updated the current language version to 2.12. -* Changed the default language version when the package does not specify one. - Instead of the latest known language version, the language version of the - SDK (against which analysis is done, not necessary the same as used to run - the analyzer) is used. - -## 0.40.5 -* Deprecated `GenericTypeAliasElement`. Use `FunctionTypeAliasElement`. -* Read imports, exports, and parts on demand in `AnalysisDriver`. - Specifically, `parseFileSync` will not read any referenced files. -* Types are not set anymore for classes/constructors/getters of - identifiers in metadata (still set in arguments). - -## 0.40.4 -* Deprecated `IndexExpression.auxiliaryElements` and - `SimpleIdentifier.auxiliaryElements`. Use `CompoundAssignmentExpression`. -* Removed internal `getReadType`, use `CompoundAssignmentExpression`. -* Bug fixes: 34699, 43524, 42990. - -## 0.40.3 -* Updated the current language version to `2.11`. -* Bug fixes: 43541, 27896, 28066, 28066, 43497, 43478, 28066, 43465, - 43462, 43439, 43162, 43397, 43200. - -## 0.40.2 -* Require `meta: ^1.2.3`. - -## 0.40.1 -* Added `LocalVariableElement.hasInitializer`, - `PropertyInducingElement.hasInitializer`, `ParameterElement.hasDefaultValue`. -* `ElementImpl.toString()` uses `getDisplayString(withNullability: true)`. -* Deprecated `ElementAnnotation.constantValue`, it does not guarantee that - the value has been computed. Use `computeConstantValue()` instead. -* Added `CompoundAssignmentExpression` with read/write element/type getters. - This interface is implemented by `AssignmentExpression`, `PostfixExpression` - and `PrefixExpression`. Use it instead of `staticElement` and `staticType` - of the left-hand side expressions (target expressions in case of postfix - or prefix expressions with increment operator). -* Changes to the way experiments are handled, and SDK version. -* Bug fixes: 43268, 43214, 39642, 42379, 42629, 43168, 43144, 43100, - 43032, 43073. - -## 0.40.0 -* Added `LibraryElement.featureSet`. -* Removed deprecated `EmbedderSdk` and related classes. -* `FunctionType` returned from `ExecutableElement.type` return `null` - as its `element`. Use `ExecutableElement`s directly if necessary. -* `FunctionTypeAliasElement` does not implement `FunctionTypedElement` - anymore, implements `TypeParameterizedElement` instead. -* Removed deprecated `CustomUriResolver`. -* Removed deprecated `ExplicitSourceResolver`, `FileUriResolver`, - `LocalSourcePredicate`, `PackageUriResolver`, `RelativeFileUriResolver`. -* Removed deprecated `ErrorCode` instances. -* The `withNullability` flag in `DartType.getDisplayString()` is now required. -* Removed deprecated `DartType.substitute2`, and `FunctionType.substitute3`, - use `ClassElement.instantiate`, `FunctionTypeAliasElement.instantiate()`, - or `FunctionType.instantiate()`. -* Removed deprecated `FunctionType.boundTypeParameters`, use `typeFormals` - for now. Later, it will be deprecated, and replaced with `typeParameters`. -* Removed `InterfaceType.instantiate()`, `InterfaceType.substitute4`, - use `ClassElement.instantiate()`. -* Removed `typeParameters` and `instantiate()` from `ParameterizedType`. - Use `typeParameters` and `instantiate()` from `ClassElement`. -* Removed deprecated methods from `DeclaredVariables`. -* Removed deprecated `typeProvider` and `typeSystem` getters. - Use corresponding `LibraryElement` getters instead. -* Removed deprecated options from `AnalysisOptions`. -* Removed deprecated `ClassElement.hasReferenceToSuper`. -* Removed deprecated `DartType.isObject`. - Use `DartType.isDartCoreObject` instead. -* Removed deprecated declarations in `AnalysisContext` and `ContextLocator`. -* Removed deprecated libraries. -* Removed deprecated declarations from TypeProvider. -* Removed deprecated `ParseResult` and `ResolveResult`. -* Removed deprecated `AnalysisContext.typeProvider` and `typeSystem`. - Use the corresponding getters of `LibraryElement`. -* Removed deprecated methods of `AnalysisSession`. -* Removed deprecated declarations from `dart/ast/ast.dart`. -* Removed deprecated methods from `AstFactory`. -* Removed deprecated `parseFile2`.. -* Removed deprecated `TypeDefiningElement.type`. -* Features in `Feature` are not constants anymore. -* Replaced `Feature.firstSupportedVersion` with `releaseVersion`. - -## 0.39.17 -* Depend on cli_util 0.2.0. - -## 0.39.16 -* Added `TypeVisitorWithArgument` and `DartType.acceptWithArgument`. -* Bumped the analyzer's SDK requirement to `>=2.7.0`, so that extension methods - can be used within the analyzer implementation. Previously it was `2.6.0`, - but there is an [issue](https://github.com/dart-lang/sdk/issues/42888). - -## 0.39.15 -* Move `asInstanceOf(ClassElement)` to `DartType`, so that it is also - supported for `TypeParameterType` when its bound implements the - requested interface. -* Fixed invalid implicit downcast in `InterfaceType.allSupertypes`. -* The internal `currentVersion` of the language updated to `2.10`. -* Bug fixes: 41065, 42797, 42770, 42668. - -## 0.39.14 -* Removed `defaultSdkDirectory()` and `getSdkProperty()` from internal - `FolderBasedDartSdk`. It is up to the clients to decide how to - find SDK, for example using `package:cli_util`. -* Fixed `LintDriver` for the new way to access `WorkspacePackage`. -* Deprecated `Scope.lookup()`, use `Scope.lookup2()` instead. -* Updated implementations of `ContextBuilder.createContext()` and - `ContextLocator.locateContexts` to use the current SDK if `sdkPath` - is not provided. -* Bug fixes: #41981, #29731, #42720, #33545, #42599, #42699. - -## 0.39.13 -* Added 'dart/sdk/build_sdk_summary.dart' with `buildSdkSummary`. -* Added `DynamicType`, `NeverType`, and `VoidType` interfaces. -* Added `TypeVisitor` and `DartType.accept(TypeVisitor)`. -* Changed `ConstructorElement.returnType` to `InterfaceType`. -* Added `InterfaceType.allSupertypes`. -* Added `InterfaceType.asInstanceOf(ClassElement)`. -* Removed deprecated internal `bogus-disabled` and `bogus-enabled`. -* Added `Scope`, `LibraryElement.scope`, and `PrefixElement.scope`. -* Bug fixes: #32192, #42620, #42256, #42605. - -## 0.39.12 -* Deprecated `canUseSummaries` in `DartSdkManager` constructor. - Summaries are not supported this way for SDK. -* Set uri for implicit dart:core import. -* Add overrideKnownFeaturesAsync() for DartDoc testing. -* Remove DartSdk.useSummary. -* Move TypeSystemImpl to src/dart/element/type_system.dart - -## 0.39.11 -* Deprecated `ClassElement.hasReferenceToSuper`. - It was used internally, should not be part of API. -* Deprecated `LibraryElement.languageVersionMajor/minor`. - Use `LibraryElement.languageVersion` to access more specific information. -* Bug fixes: #42007, #42474, #37293, #42385, #36315, #42356, #42274, #42321, - #42337, #27387, #34806, #37810, #41072, #42278, #38306, #35036, #23353, - #42178, #42216, #42201. - -## 0.39.10 -* Restored the default constructor in internal `SummaryBuilder`, - and the `featureSet` named parameter in `build`, for `build_resolvers` - compatibility. See #42163. - -## 0.39.9 -* Deprecated `DartType.isObject`, use `DartType.isDartCoreObject` for - consistency with other similar getters. -* Deprecated `InstanceCreationExpression.staticElement`, use - `constructorName.staticElement` instead, like for `MethodInvocation`. -* Added new error code: REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR. -* Bug fixes: #34370, #35710, #37552, #38676, #38799, #39644, #41151, #41592, - #41614, #41724, #41741, #41797, #41803, #41844, #41997, #42077, #42093, - and #42122. - -## 0.39.8 -* Deprecated `VariableElement.constantValue`, it does not guarantee that - the value has been computed. Use `computeConstantValue()` instead. -* Deprecated the following members of `AnalysisOptions`: - `analyzeFunctionBodiesPredicate`, `disableCacheFlushing`, - `enableLazyAssignmentOperators`, `generateImplicitErrors`, - `generateSdkErrors`, `patchPaths`, `preserveComments`, - `trackCacheDependencies`, and `resetToDefaults`. -* Bug fixes: #35716, #37048, #40014, #40957, #41479, #41521, #41551, #41555, - #41557, #41593, #41603, #41630, #41632, #41645. - -## 0.39.7 -* Added new error codes: ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING and - THROW_OF_INVALID_TYPE. -* Changed error code NULLABLE_TYPE_IN_CATCH_CLAUSE to a hint. -* Bug fixes: #40554, #41378, #41399, #41412, and #41470. - -## 0.39.6 -* Added Window and DocumentFragment to analyzer's mock SDK. These are required - for upcoming changes to the unsafe_html lint. - -## 0.39.5 -* Deprecated `ClassElement.instantiateToBounds()` and - `FunctionTypeAliasElement.instantiateToBounds()`. With the null-safety - feature, type arguments derived from type parameter bounds cannot be used as - is, and might require erasing nullability, when the element is instantiated - from a legacy library. Use `TypeSystem.instantiateToBounds2()` instead. -* Deprecated `DeclaredVariables.getBool/getInt/getString()` and - `TypeProvider.nullObject`. These methods are used internally for constants - computation, and should not be used by clients. -* Deprecated `AstFactory.indexExpressionForCascade()`. Please use - `indexExpressionForCascade2` instead. -* Deprecated `AstFactory.indexExpressionForTarget()`. Please use - `indexExpressionForTarget2` instead. -* Deprecated `ClassElement.isOrInheritsProxy` and `ClassElement.isProxy`. The - `@proxy` annotation is deprecated in the language, and will be removed. -* Added new error codes: BODY_MIGHT_COMPLETE_NORMALLY, - CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE, - DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE, LATE_FINAL_LOCAL_ALREADY_ASSIGNED, - SWITCH_CASE_COMPLETES_NORMALLY, EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER, - FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER, GETTER_CONSTRUCTOR, - MEMBER_WITH_CLASS_NAME, SETTER_CONSTRUCTOR, TYPE_PARAMETER_ON_OPERATOR, and - VOID_WITH_TYPE_ARGUMENTS. -* Renamed error code DEFAULT_LIST_CONSTRUCTOR_MISMATCH to - DEFAULT_LIST_CONSTRUCTOR. This reflects a spec change: after null safety is - enabled, it will be an error to call the default `List` constructor under all - circumstances. -* Added new warning code: INVALID_NULL_AWARE_OPERATOR. -* Renamed warning code DEAD_NULL_COALESCE to DEAD_NULL_AWARE_EXPRESSION, to - reflect the fact that it applies both to if-null expressions (`??`) and - if-null compound assignment expressions (`??=`). -* Split warning code MISMATCHED_GETTER_AND_SETTER_TYPES into two codes: - GETTER_NOT_ASSIGNABLE_SETTER_TYPES and GETTER_NOT_SUBTYPE_SETTER_TYPES. -* Coalesced warning codes UNNECESSARY_NULL_AWARE_CALL and - UNNECESSARY_NULL_AWARE_SPREAD into one warning code: - INVALID_NULL_AWARE_OPERATOR. -* Added new hint codes: EQUAL_ELEMENTS_IN_SET, EQUAL_KEYS_IN_MAP, - INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION, UNNECESSARY_NULL_COMPARISON_FALSE, - and UNNECESSARY_NULL_COMPARISON_TRUE. -* Downgraded warning INVALID_USE_OF_NEVER_VALUE to hint RECEIVER_OF_TYPE_NEVER. -* Re-introduced strong mode codes: DYNAMIC_INVOKE, IMPLICIT_DYNAMIC_FIELD, - IMPLICIT_DYNAMIC_FUNCTION, IMPLICIT_DYNAMIC_INVOKE, - IMPLICIT_DYNAMIC_LIST_LITERAL, IMPLICIT_DYNAMIC_MAP_LITERAL, - IMPLICIT_DYNAMIC_METHOD, IMPLICIT_DYNAMIC_PARAMETER, IMPLICIT_DYNAMIC_RETURN, - IMPLICIT_DYNAMIC_TYPE, and IMPLICIT_DYNAMIC_VARIABLE. These were removed in - version 0.39.3, but it turns out they are actually needed (see - https://github.com/dart-lang/sdk/issues/40129). -* Fixed bugs 35940, 37122, 38554, 38666, 38791, 38990, 39059, 39597, 39694, - 39762, 39791, 39833, 39875, 39876, 39917, 39939, 39976, 40033, 40055, 40057, - 40110, 40129, 40221, 40279, 40283, 40287, 40299, 40304, 40316, 40333, 40392, - 40394, 40396, 40398, 40413, 40414, 40460, 40482, 40500, 40538, 40546, 40547, - 40572, 40578, 40603, 40609, 40677, 40689, 40701, 40704, 40734, 40764, 40837, - 40865, 40915, 40931, 40941, 40955, 40956, 40958, 40959, 41019, 41036, 41050, - 41095, 41130, and 41180. - -## 0.39.4 -* Deprecated `DartType.name`, use `element` or `getDisplayString()` instead. -* Fixed bugs 35108 and 39996. - -## 0.39.3 -* Bumped the analyzer's SDK requirement to `>=2.6.0`, so that extension methods - can be used within the analyzer implementation. -* Deprecated `ErrorReporter.source` setter. One file - one reporter. -* Deprecated `Element.getAncestor`. Use thisOrAncestorMatching or - thisOrAncestorOfType instead. -* Deprecated `DartType.displayName`. Use getDisplayString instead. -* Deprecated the following methods in `InterfaceType`: `lookupGetter`, - `lookUpGetterInSuperclass`, `lookUpInheritedGetter`, - `lookUpInheritedGetterOrMethod`, `lookUpInheritedMethod`, - `lookUpInheritedSetter`, `lookUpMethod`, `lookUpMethodInSuperclass`, - `lookUpSetter`, and `lookUpSetterInSuperclass`. Use `lookUpGetter2()`, - `lookUpMethod2()`, or `lookUpSetter2()` instead, with `concrete` or - `inherited` flags as necessary. -* Deprecated `ErrorReporter.reportTypeErrorForNode`. Use `reportErrorForNode` - instead. -* Added new error codes: EXPORT_LEGACY_SYMBOL and DEAD_NULL_COALESCE. -* Removed error codes CONST_WITH_INVALID_TYPE_PARAMETERS and - NEW_WITH_INVALID_TYPE_PARAMETERS. WRONG_NUMBER_OF_TYPE_ARGUMENTS is now - reported instead. -* Removed error codes: DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, - INVALID_OPTIONAL_PARAMETER_TYPE. -* Reclassified error codes as compile time errors: BREAK_LABEL_ON_SWITCH_MEMBER, - CONTINUE_LABEL_ON_SWITCH, PART_OF_UNNAMED_LIBRARY. -* Removed error codes: ASSIGNMENT_CAST, StrongModeCode.DOWN_CAST_COMPOSITE, - DOWN_CAST_IMPLICIT, DOWN_CAST_IMPLICIT_ASSIGN, DYNAMIC_CAST, DYNAMIC_INVOKE, - IMPLICIT_DYNAMIC_FIELD, IMPLICIT_DYNAMIC_FUNCTION, IMPLICIT_DYNAMIC_INVOKE, - IMPLICIT_DYNAMIC_LIST_LITERAL, IMPLICIT_DYNAMIC_MAP_LITERAL, - IMPLICIT_DYNAMIC_METHOD, IMPLICIT_DYNAMIC_PARAMETER, IMPLICIT_DYNAMIC_RETURN, - IMPLICIT_DYNAMIC_TYPE, IMPLICIT_DYNAMIC_VARIABLE, INFERRED_TYPE, - INFERRED_TYPE_ALLOCATION, INFERRED_TYPE_CLOSURE, INFERRED_TYPE_LITERAL, and - NON_GROUND_TYPE_CHECK_INFO. These were used internally by the analyzer for - testing and were not exposed to users. -* Fixed bugs 37116, 38281, 38859, 39524, 39598, 39651, 39667, 39668, 39709, - 39711, 39752, 39773, 39848, 39849, and 39880. - -## 0.39.2+1 -* Fixed bug #39702. - -## 0.39.2 -* Deprecated `AnalysisSession.typeProvider` and `AnalysisSession.typeSystem`. - Please use the corresponding getters in `LibraryElement` instead. -* Added new error codes: AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER, - DEFERRED_IMPORT_OF_EXTENSION, LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR, - WRONG_TYPE_PARAMETER_VARIANCE_POSITION, and - WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE. -* Added new hint codes: INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN, - INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS, - INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE, - INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER, - INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX, - INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS, and - INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES. -* Changed error code TYPE_PARAMETER_ON_CONSTRUCTOR from a CompileTimeErrorCode - to a ParserErrorCode. -* Split warning code RETURN_OF_INVALID_TYPE into two warnings: - RETURN_OF_INVALID_TYPE_FROM_FUNCTION and RETURN_OF_INVALID_TYPE_FROM_METHOD. -* Merged warning codes CONST_WITH_ABSTRACT_CLASS and NEW_WITH_ABSTRACT_CLASS - into INSTANTIATE_ABSTRACT_CLASS. -* Removed warning code MIXED_RETURN_TYPES (this is now allowed by the language - spec). -* Bug fixes: 33745, 35677, 35677, 37504, 37936, 38506, 38551, 38734, 38813, - 38878, 38953, 38992, 39051, 39115, 39117, 39120, 39192, 39250, 39267, 39380, - 39389, 39402, 39407, 39476, 39509, 39532, 39563, 39618. - -## 0.39.1 -* Deprecated `DartType.substitute2()`. Use `ClassElement.instantiate()` - or `FunctionTypeAliasElement.instantiate()` instead. -* Deprecated `ParameterizedType.instantiate()` and - `InterfaceType.instantiate()`. Use `ClassElement.instantiate()` instead. - Using `FunctionType.instantiate()` is still valid. -* Deprecated `FunctionTypeAliasElement.instantiate2`, use `instantiate2`. - In the next version `instantiate2` will be removed. -* Deprecated `ParameterizedType.typeParameters`. Please use - `ClassElement.typeParameters or FunctionType.typeFormals` instead. -* Bug fixes: 27617, 34378, 35607, 38494, 38582, 38583, 38643, 38761, 38991, - 39089, 39111, 39156, 39158, 39170, 39171, 39178. - -## 0.39.0 -* Removed deprecated `DartType.isEquivalentTo`. -* Removed `useDart2jsPaths` argument in `FolderBasedDartSdk` constructor. - Dartium does not exist anymore, so there is just one `dart:html`. -* Removed several unused members of `SourceFactory`: `context`, - `localSourcePredicate`, `clone`, `fromEncoding`, `isLocalSource`. -* Removed deprecated method `Element.computeNode`. -* Removed deprecated getter `CompilationUnitElement.unit`. -* Removed deprecated method `Element.computeDocumentationComment`. -* Removed unused `wrapped.dart` with `WrappedLibraryElement`, etc. -* Removed deprecated 'bestElement', 'bestType', 'propagatedElement', - 'propagatedType', etc. Use 'staticElement' and 'staticType' instead. -* Removed deprecated 'Declaration.element'. - Use 'Declaration.declaredElement' instead. -* Removed deprecated 'Expression.precedence2'. Use 'precedence' instead. -* Removed `ResolutionMap resolutionMap`. Use corresponding accessors - on AstNode(s) directly to get elements and types. -* Removed 'InheritanceManager2'. Use 'InheritanceManager3' instead. -* Removed 'InheritanceManager'. Use 'InheritanceManager3' instead. -* Removed deprecated methods in `DartType`: `flattenFutures`, - `isAssignableTo`, `isEquivalentTo`, `isMoreSpecificThan`, - `isSubtypeOf`, `isSupertypeOf`, `isDirectSupertypeOf`. - Use corresponding methods of `TypeSystem` instead. -* Removed deprecated getters for checking a specific annotations on - 'Element': `isAlwaysThrows`, `isDeprecated`, `isFactory`, `isJS`, - `isOverride`, `isProtected`, `isRequired`, `isVisibleForTesting`. - Use corresponding `hasXyz` getters. -* Removed 'LocalElement.visibleRange'. - Visible ranges of local variables and functions can be computed when - AST is available. -* Removed unused `LibraryElement.libraryCycle`. -* Removed `ElementHandle` and `ElementResynthesizer`. -* Remove `ElementBuilder`, `DeclarationResolver`, `DirectiveResolver`, - `TypeParameterBoundsResolver`, `TypeResolverVisitor`, etc. - Use `ResolutionVisitor` instead, it combines all these operations. -* Removed `FunctionTypeAliasElement.instantiate`, use `instantiate2` for now. - In the next version `instantiate` will be re-introduced with the same - signature and semantics as `instantiate2`, and `instantiate2` will be - deprecated and removed in the next breaking change version. -* Stop setting types for identifiers where they are not expressions. - Specifically, where a SimpleIdentifier is the name of a declaration, - or Identifier is the name of the class in a TypeName. -* Removed transitional `InheritanceManagerBase`. -* Removed deprecated method `ArgumentList.correspondingPropagatedParameters`. - Use `ArgumentList.correspondingStaticParameters` instead. -* Removed deprecated getter `PrefixElement.importedLibraries`. It was never - implemented. -* Removed deprecated getter `VariableElement.isPotentiallyMutatedInClosure` and - `VariableElement.isPotentiallyMutatedInScope`. Please use the corresponding - methods in `FunctionBody` instead. -* Bug fixes: 33441, 35777, 35993, 37898, 38560, 38803, 38811, 38900, 38911. - -## 0.38.5 -* Added the interface `PromotableElement`, which representing - variables that can be type promoted (local variables and parameters, - but not fields). -* Deprecated the boolean `AnalysisDriver.useSummary2`. Summary1 support has - been removed, so clients should assume Summary2 is in use now. -* Deprecated the constructor argument `useDart2jsPaths` for SdkLibrariesReader. - We now always use Dart2js paths. -* Bug fixes: #37608, #37708, #37867, #38498, #38565, #38572, #38589, #38641, - #38653, #38667, #38695, #38706. - -## 0.38.4 -* Bug fixes: #33300, #38484, #38505. - -## 0.38.3 -* Deprecated the following codes from `StaticWarningCode`. Please use the - corresponding error codes from `CompileTimeErrorCode` instead: - * `EXTRA_POSITIONAL_ARGUMENTS` - * `EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED` - * `IMPORT_OF_NON_LIBRARY` - * `NOT_ENOUGH_REQUIRED_ARGUMENTS` - * `REDIRECT_TO_MISSING_CONSTRUCTOR` - * `REDIRECT_TO_NON_CLASS` - * `UNDEFINED_CLASS` - * `UNDEFINED_NAMED_PARAMETER` -* Bug fixes: #33749, #35985, #37708, #37857, #37858, #37859, #37945, #38022, - #38057, #38071, #38091, #38095, #38105, #38113, #38198, #38202, #38203, - #38261, #38282, #38365, #38417, #38448, #38449. - -## 0.38.2 -* The type of `FunctionTypeAlias.declaredElement` has been refined to - `FunctionTypeAliasElement`. Since the new type is a refinement of - the old one, the only effect on clients should be to make certain - casts unnecessary. -* Deprecated `HintCode.INVALID_REQUIRED_PARAM` and replaced it with more - specific hints, `HintCode.INVALID_REQUIRED_NAMED_PARAM`, - `HintCode.INVALID_REQUIRED_OPTIONAL_POSITIONAL_PARAM`, and - `HintCode.INVALID_REQUIRED_POSITIONAL_PARAM` to address #36966. -* Deprecated `CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS`. It - has been renamed to - `CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS`. - -## 0.38.1 -* LinterVisitor support for extension method AST nodes. - -## 0.38.0 -* The deprecated method `AstFactory.compilationUnit2` has been removed. Clients - should switch back to `AstFactory.compilationUnit`. -* Removed the deprecated constructor `ParsedLibraryResultImpl.tmp` and the - deprecated method `ResolvedLibraryResultImpl.tmp`. Please use - `AnalysisSession.getParsedLibraryByElement` and - `AnalysisSession.getResolvedLibraryByElement` instead. -* Removed `MethodElement.getReifiedType`. -* The return type of `ClassMemberElement.enclosingElement` was changed from - `ClassElement` to `Element`. - -## 0.37.1+1 -* Reverted an unintentional breaking API change (the return type of - `ClassMemberElement.enclosingElement` was changed from `ClassElement` to - `Element`). This change will be postponed until 0.38.0. - -## 0.37.1 -* Added the getters `isDartCoreList`, `isDartCoreMap`, `isDartCoreNum`, - `isDartCoreSet`, `isDartCoreSymbol`, and `isDartCoreObject` to `DartType`. -* Added the method `DartObject.toFunctionValue`. -* Deprecated the `isEquivalentTo(DartType)` method of `DartType`. - The operator `==` now correctly considers two types equal if and - only if they represent the same type as defined by the spec. -* Deprecated the `isMoreSpecificThan(DartType)` method of `DartType`. - Deprecated the `isMoreSpecificThan(DartType)` method of `TypeSystem`. - Deprecated the `isSupertypeOf(DartType)` method of `TypeSystem`. - Use `TypeSystem.isSubtypeOf(DartType)` instead. -* Deprecated methods `flattenFutures`, `isAssignableTo` of `DartType`. - Use `TypeSystem.flatten()` and `TypeSystem.isAssignableTo` instead. -* Deprecated InheritanceManager2, and replaced with InheritanceManager3. - InheritanceManager3 returns ExecutableElements, not FunctionType(s). -* Added the optional parameter `path` to `parseString`. -* Changed `TypeSystem.resolveToBound(DartType)` implementation to do - what its documentation says. -* This version of the analyzer should contain all the necessary parsing support - and AST data structures for the experimental "extension-methods" feature. - Further element model improvements needed to support extension methods will be - published in 0.38.x. -* Deprecated `InterfaceType.isDirectSupertypeOf`. There is no replacement; this - method was not intended to be used outside of the analyzer. - -## 0.37.0 -* Removed deprecated getter `DartType.isUndefined`. -* Removed deprecated class `SdkLibrariesReader`. -* Removed deprecated method `InstanceCreationExpressionImpl.canBeConst`. -* The `AstFactory.compilationUnit` method now uses named parameters. Clients - that prepared for this change by switching to `AstFactory.compilationUnit2` - should now switch back to `AstFactory.compilationUnit`. -* Removed `AstNode.getAncestor`. Please use `AstNode.thisOrAncestorMatching` or - `AstNode.thisOrAncestorOfType`. -* Removed deprecated getter `TypeSystem.isStrong`, and its override - `Dart2TypeSystem.isStrong`. -* Removed the deprecated getter `AnalysisError.isStaticOnly` and the deprecated - setters `AnalysisError.isStaticOnly` and `AnalysisError.offset`. -* Removed the `abstract` setter in `ClassElementImpl`, `EnumElementImpl`, - `MethodElementImpl`, and `PropertyAccessorElementImpl`. `isAbstract` should - be used instead. -* Removed methods `AstVisitor.ForStatement2`, `ListLiteral.elements2`, - `SetOrMapLiteral.elements2`, `AstFactory.forStatement2`, and - `NodeLintRegistry.addForStatement2`, as well as class `ForStatement2`. Use - the variants without the "2" suffix instead. -* Changed the signature and behavior of `parseFile` to match `parseFile2`. - Clients that switched to using `parseFile2` when `parseFile` was deprecated - should now switch back to `parseFile`. -* Removed Parser setters `enableControlFlowCollections`, `enableNonNullable`, - `enableSpreadCollections`, and `enableTripleShift`, and the method - `configureFeatures`. Made the `featureSet` parameter of the Parser - constructor a required parameter. - -## 0.36.4 -* Deprecated the `isNonNullableUnit` parameter of the `TypeResolverVisitor` - constructor. TypeResolverVisitor should now be configured using the - `featureSet` parameter. -* Refined the return type of the getter `TypeParameter.declaredElement`. It is - always guaranteed to return a `TypeParameterElement`. -* Deprecated the `abstract` setter in `ClassElementImpl`, `EnumElementImpl`, - `MethodElementImpl`, and `PropertyAccessorElementImpl`. `isAbstract` should - be used instead. -* Changed the way function types are displayed from e.g. `(int) -> void` to - `void Function(int)`. This is more consistent with the syntax of Dart, and it - will avoid ambiguities when nullability is added to the type system. This - impacts to value returned by `FunctionType.displayName` and - `FunctionType.toString` and `ExecutableElement.toString`. Client code might be - broken if it depends on the content of the returned value. -* Introduced the function `parseString` to the public API. This can be used in - place of the deprecated functions `parseCompilationUnit` and - `parseDirectives`. Note that there is no option to parse only directives, - since this functionality is broken anyway (`parseDirectives`, despite its - name, parses the entire compilation unit). -* Changed the return type of `ClassTypeAlias.declaredElement` to `ClassElement`. - There is no functional change; it has always returned an instance of - `ClassElement`. -* Deprecated `parseFile`. Please use `parseFile2` instead--in addition to - supporting the same `featureSet` and `throwIfDiagnostics` parameters as - `parseString`, it is much more efficient than `parseFile`. -* Added more specific deprecation notices to `package:analyzer/analyzer.dart` to - direct clients to suitable replacements. -* Deprecated the enable flags `bogus-disabled` and `bogus-enabled`. Clients - should not be relying on the presence of these flags. -* Deprecated the constructor parameter - ConstantEvaluationEngine.forAnalysisDriver, which no longer has any effect. -* Deprecated ElementImpl.RIGHT_ARROW. - -## 0.36.3 -* Deprecated `AstFactory.compilationUnit`. In a future analyzer release, this - method will be changed so that all its parameters are named parameters. - Clients wishing to prepare for this should switch to using - `AstFactory.compilationUnit2`. -* Deprecated Parser setters `enableControlFlowCollections`, `enableNonNullable`, - `enableSpreadCollections`, and `enableTripleShift`, as well as the - recently-introduced method `configureFeatures`. Parsers should now be - configured by passing a FeatureSet object to the Parser constructor. -* Deprecated `AnalysisError.isStaticOnly`. -* Deprecated `AnalysisError.offset` setter. -* Added method `LinterContext.canBeConstConstructor`. -* Bug fixes: #36732, #36775. - -## 0.36.2 -* Bug fixes: #36724. - -## 0.36.1 -* Deprecated `DartType.isUndefined`, and now it always returns `false`. -* The "UI as code" features (control_flow_collections and spread_collections) - are now enabled. -* Bug fixes: #32918, #36262, #36380, #36439, #36492, #36529, #36576, #36667, - #36678, #36691. - -## 0.36.0 -* Changed the return type of `Expression.precedence` to `Precedence`. Clients - that prepared for this change by switching to `Expression.precedence2` should - now return to using `Expression.precedence`. -* AST cleanup related to the "UI as code" feature: - * Removed the following AST node types: - * `ForEachStatement` (use `ForStatement` instead) - * `MapLiteral` and `MapLiteral2` (use `SetOrMapLiteral` instead) - * `SetLiteral` and `SetLiteral2` (use `SetOrMapLiteral` instead) - * `ListLiteral2` (use `ListLiteral` instead) - * Deprecated `ForStatement2` (use `ForStatement` instead) - * Removed the following visit methods: - * `visitForEachStatement` (override `visitForStatement` instead) - * `visitMapLiteral` and `visitMapLiteral2` (override `visitSetOrMapLiteral` - instead) - * `visitSetLiteral` and `visitSetLiteral2` (override `visitSetOrMapLiteral` - instead) - * `visitListLiteral2` (override `visitListLiteral` instead) - * Deprecated the `visitForStatement2` visit method (use `VisitForStatement` - instead) - * Removed the following AstFactory methods: - * `mapLiteral` and `mapLiteral2` (use `setOrMapLiteral` instead) - * `setLiteral` and `setLiteral2` (use `setOrMapLiteral` instead) - * `listLiteral2` (use `listLiteral` instead) - * Deprecated `AstFactory.forStatement2`, and introduced - `AstFactory.forStatement` to replace it - * Changed the type of the getter `ListLiteral.elements` to - `NodeList` - * Deprecated `ListLiteral.elements2` (use `ListLiteral.elements` instead) - * Deprecated `SetOrMapLiteral.elements2`, and introduced - `SetOrMapLiteral.elements` to replace it - * Deprecated `NodeLintRegistry.addForStatement2` (use - `NodeLintRegistry.addForStatement` instead) -* Bug fixes: #36158, #36212, #36255 - -## 0.35.4 -* Deprecated AST structures that will no longer be used after the - control_flow_collections and spread_collections experiments are enabled. The - following AST node types are deprecated: - * `ForEachStatement` (use `ForStatement2` instead) - * `ForStatement` (use `ForStatement2` instead) - * `MapLiteral` (use `SetOrMapLiteral` instead) - * `SetLiteral` (use `SetOrMapLiteral` instead) -* Deprecated visit methods that will no longer be used after the - control_flow_collections and spread_collections experiments are enabled. The - following visit methods are deprecated: - * `visitForEachStatement` (override `visitForStatement2` instead) - * `visitForStatement` (override `visitForStatement2` instead) - * `visitMapLiteral` (override `visitSetOrMapLiteral` instead) - * `visitSetLiteral` (override `visitSetOrMapLiteral` instead) -* Deprecated ASTFactory methods that will no longer be available after the - control_flow_collections and spread_collections experiments are enabled. The - following factory methods are deprecated: - * `mapLiteral` and `mapLiteral2` (use `setOrMapLiteral` instead) - * `setLiteral` and `setLiteral2` (use `setOrMapLiteral` instead) -* Bug fixes: #33119, #33241, #35747, #35900, #36048, #36129 -* The analyzer no longer uses `package:html` (see #35802) - -## 0.35.3 -* Further updates to the AST structure for the control_flow_collections and - spread_collections experiments. The following AST node types will be - deprecated soon: - * `ForEachStatement` (use `ForStatement2` instead) - * `ForStatement` (use `ForStatement2` instead) - * `MapLiteral` (use `SetOrMapLiteral` instead) - * `SetLiteral` (use `SetOrMapLiteral` instead) -* Deprecated `Expression.precedence`. In analyzer version 0.36.0, its return - type will be changed to `Precedence`. Clients that wish to prepare for the - change can switch to `Expression.precedence2`. -* Bug fixes: #35908, #35993 (workaround). - -## 0.35.2 -* Updated support in the AST structure for the control_flow_collections and - spread_collections experiments. The following methods are now deprecated: - * `AstFactory.mapLiteral2` and `AstFactory.setLiteral2` (replaced by - `AstFactory.setOrMapLiteral`). - * `AstVisitor.visitListLiteral2` (clients should not need to override this - anymore). - * `AstVisitor.visitMapLiteral2 and AstVisitor.visitSetLiteral2` (replaced by - `AstVisitor.visitSetOrMapLiteral`). -* Started to add support for strict-inference as an analysis option. -* Bug fixes: #35870, #35922, #35936, #35940, - https://github.com/flutter/flutter-intellij/issues/3204 - -## 0.35.1 -* The new "set literals" language feature is now enabled by default. -* The dev_dependency analysis_tool was created so that clients do not have to - depend on code that is used internally in the analyzer at development time. -* The `InheritanceManager` class is now deprecated. The new - `InheritanceManager2` class now supports accessing inherited interface/class - maps. -* Added quick assists to support set literals. -* Added the ability for linter tests to drive the analyzer using custom analysis - options. -* Updated support in the AST structure for the control_flow_collections and - spread_collections experiments. The new AST structures are still in - development. -* Bug fixes: #34437, #35127, #35141, #35306, #35621. - -## 0.35.0 -* Added support in the AST structure for the control_flow_collections and - spread_collections experiments. This includes adding new visitor methods to - `AstVisitor`, which will need to be implemented by any classes that implement - `AstVisitor` directly. Concrete implementations were added to other visitor - classes (such as `RecursiveAstVisitor`) so that clients that extend those - other classes will not be impacted. -* Removed `EMPTY_LIST` constants. Please use `const <...>[]` instead. -* Disabled support for the task model. Please use the new `AnalysisSession` - API. -* Removed `StrongTypeSystemImpl`. Please use `Dart2TypeSystem` instead. -* Made ERROR the default severity for StaticWarningCode. We no longer need to - promote warnings to errors in "strong mode" because strong mode is the only - mode. -* Added exact type analysis for set literals (#35742). -* Bug fixes: #35305, #35750. - -## 0.34.3 -* Non-breaking AST changes in support for the control_flow_collections and - spread_collections experiments. Clients who wish to begin adding support for - these experiments can depend on this release of the analyzer and begin writing - visit methods. The visit methods won't be added to the AstVisitor base class - until 0.35.0. -* Bug fixes: #35551, #35708, #35723. - -## 0.34.2 -* Removed support for the `@checked` annotation. Please use the `covariant` - keyword instead (#28797). -* Did additional work on the new set_literals and constant_update_2018 features. -* Began adding a string representation of initializer expressions to summaries - (#35418). -* Added a pub aware workspace so that pub packages can be handled properly. -* Added logging in an effort to track down #35551. -* Split off DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE from DEPRECATED_MEMBER_USE - (#30084). -* Removed the unused hint code INVALID_ASSIGNMENT. -* Added a hint enforcing the contract of `@literal`: - NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR. -* Added a hint INVALID_LITERAL_ANNOTATION (#34259). -* Fixed handling of @immutable on mixins. -* Did work on @sealed annotation for classes and mixins. -* Bug fixes: #25860, #29394, #33930, #35090, #35441, #35458, #35467, #35548. - -## 0.34.1 -* Added logic to report a hint if a deprecated lint is specified in the user's - analysis_options.yaml file, or if a lint is specified twice. -* Added a note to the `UriResolver` documentation alerting clients of an - upcoming breaking change. -* Improved parser recovery. -* Speculative work on fine-grained dependency tracking (not yet enabled). -* Initial support for new language features set_literals and - constant_update_2018. -* Early speculative work on non-nullable types. -* Added AnalysisDriver.resetUriResolution(). -* Deprecated TypeSystem.isStrong. -* Added WorkspacePackage classes, for determining whether two files are in the - "same package." -* Added a public API for the TypeSystem class. -* Bug fixes: #33946, #35151, #35223, #35241, #35438. - -## 0.34.0 -* Support for `declarations-casts` has been removed and the `implicit-casts` - option now has the combined semantics of both options. This means that users - that disable `implicit-casts` might now see errors that were not previously - being reported. -* Minor changes to the AnalysisSession and AnalysisDriver APIs to make it easier - for clients to transition away from using the task model. -* Minor changes to the linter API to make it easier for lint rules to define - their own lint codes. -* Add a version of getAncestor that matches by type without a closure. -* Add an AST structure for set literals. -* Bug fixes: #35162, #35230, #34733, #34741, #33553, #35090, #32815, #34387, - #34495, #35043, #33553, #34906, #34489. - -## 0.33.6+1 -* Added a note to the `UriResolver` documentation alerting clients of an - upcoming breaking change. - -## 0.33.6 -* Deprecated `AstNode.getAncestor` and introduced - `AstNode.thisOrAncestorMatching` as its replacement. - -## 0.33.5 -* Add AnalysisSession.getResolvedLibrary()/ByElement() APIs. - -## 0.33.4 -* Add a hint when either Future or Stream are imported from dart:core in a package that is expected to work with an SDK before 2.1 where they were required to be imported from dart:async. -* Add a new "deprecated" maturity for lints -* Don't report DEPRECATED_MEMBER_USE for deprecated mixins, top-level variables, and class fields. -* Various bug fixes. - -## 0.33.3+2 -* Update SDK requirement to 2.1.0-dev.5.0. From now on, the analyzer may import - Future from dart:core. (#35158) - -## 0.33.3+1 -* Fix missing import of dart:async. (#35158) - -## 0.33.3 -* Backport Parsed/ResolvedLibraryResultImpl and ElementDeclarationResult. - -## 0.33.2 -* Protect against self-referencing classes in InheritanceManager2. (#34333) -* Introduce API so that the linter can be migrated away from Element.context. - -## 0.33.1 -* Fix circular typedef stack overflow. (#33599) -* Check that the implemented member is a valid override of the member from - the super constraint. (#34693) -* Begin replacing InheritanceManager with InheritanceManager2 and - deprecate older members. -* Performance fixups with Analysis Driver. -* Verify the superconstraint signature invoked by a mixin. (#34896) -* In_matchInterfaceSubtypeOf, account for mixins having null. (#34907) - -## 0.33.0 -* Support handling 'class C with M', with extends missing. -* Report ABSTRACT_SUPER_MEMBER_REFERENCE as an error. -* Further support and bugfixes for Dart 2.1-style mixin declarations. -* Fixes for int2double support. -* Performance improvements for analysis and summary generation. -* Allow "yield" as a label, and "operator" as a static method name (#33672, - #33673) - -## 0.33.0-alpha.0 -* Switch to using the parser from front_end. -* Start implementing the new mixin syntax. - -## 0.32.4 -* Updated SDK constraint to <3.0.0. -* Updated to be compatible with Dart 2 void usage semantics. -* Deprecate the `AnalysisOptions.strongMode` flag. This is now hard-coded to - always return true. - -## 0.32.3 -* Pull fix in kernel package where non-executable util.dart was moved out of bin/. - -## 0.32.2 - -* Improved const evaluation analysis (new errors for `const A(B())` if `B` is non-const). -* Parser recovery improvements. - -## 0.32.1 - -* The Parser() class now by default will parse with optional new or const. This - affects many APIs, for instance, `analyzer.dart`'s `parseCompilationUnit()`. -* Add the ability to specify a pathContext when creating a ContextRoot (not part - of the officially supported API, but needed by some clients). -* AnalysisSession now exports resourceProvider. -* Function type parameters are now invariant. (#29014) -* New logic to find source files generated by package:build when that build - system is detected. -* Data stored by FileDataStore is now checked using CRC32. -* Add ability for the angular plugin to set ErrorVerifier.enclosingClass. - -## 0.32.0 - -* Allow annotations on enum constants. -* Analyzer fully supports being run on the VM with --preview-dart-2. -* Fix heap usage regression by not storing bytes in the file cache. -* Add AnalysisSessionHelper.getTopLevelPropertyAccessor(). -* Don't infer types when there's an irreconcilable type mismatch (#32305) -* Many fasta parser improvements. -* Use @isTest and @isTestGroup to understand executable element as a - test/group. To use, add `@isTest` annotations (from package:meta) - to the methods in their package which define a test. -```dart -@isTest -void myMagicTest(String name, FutureOr Function() body) { - test(name, body); -} -``` - When subscribed to [notifications for outlines of a test file](https://htmlpreview.github.io/?https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/doc/api.html#notification_analysis.outline), - they will include elements for UNIT_TEST_GROUP and UNIT_TEST_TEST. -* Improve guess for type name identifier. (#32765) -* Fix LineInfo.getOffsetOfLineAfter(). -* Remove some flutter specific analysis code. -* Fix resolution tests when run locally. - -## 0.31.2-alpha.2 - -* Refactoring to make element model logic sharable with - linker. (#32525, #32674) -* Gracefully handle an invalid packages file. (#32560) -* Fix silent inconsistency in top level inference. (#32394) -* Fix test to determine whether a library is in the SDK. (#32707) -* Fix for type inference from instance creation arguments. -* Make GenericFunctionTypeElementForLink implement - GenericFunctionTypeElementImpl (#32708) -* Check for missing required libraries dart:core and dart:async. (#32686) -* Add callable object support. (#32156, #32157, #32426) -* Avoid putting libraries of all analyzed units in the current - session. (too expensive) -* Deprecate the option to enable using a URI in a part-of directive. -* Support implicit call() invocation in top-level inference. (#32740) -* Don't emit errors for lint rule names. -* Allow empty flutter: sections in pubspec files. -* Remove the special casing of 'packages' files from the analyzer and analysis - server. -* Initial implementation of API to build analysis contexts (replacing - ContextLocator.locateContexts). -* Fix regression in Analyzer callable function support. (#32769) -* Several performance enhancements, including: - * Add a shared cache of FileState contents (making flutter repo analysis - ~12% faster). - * Replace SourceFactory.resolveUri() with resolveRelativeUri() in - resynthesizer. (10% faster flutter repo analysis) - * Optimize computing exported namespaces in FileState. - * Optimize computing exported namespaces in prelinker. (8% faster - flutter repo analysis) - * Add NodeLintRule and UnitLintRule that replace AstVisitor in lints. - (6% faster flutter repo analysis) -* Remove fuzzy arrow support from analyzer. (#31637) -* More fixes for running the analyzer with Dart 2. -* Add isXYZ accessors to ParameterElementForLink_VariableSetter. (#32896) -* Demote IMPORT_DUPLICATED_LIBRARY_NAMED to a warning. -* Deprecated/removed some unused classes and libraries from the public API. -* Instantiate bounds to bounds. -* Use package:path instead of AbsolutePathContext. -* Check that argument is assignable to parameter in call() (#27098) -* preview-dart-2 is now the default for the command line analyzer, also - implying strong. Use --no-strong and --no-preview-dart-2 to handle - Dart 1 code. -* Export SyntheticBeginToken and SyntheticToken from the analyzer for - angular_analyzer_plugin. -* Improve error messages for annotations involving undefined names (#27788) -* Add support for getting parse results synchronously. -* Change linter subscriptions from functions to AstVisitor(s). - -## 0.31.2-alpha.1 - -* Don't expect type arguments for class type parameters of static methods. - (#32396) -* Beginnings of changes to make analyzer code --preview-dart-2 safe, though - this version is not vetted for that. -* Infer type arguments in constructor redirections (#30855) -* Report errors on "as void" and "is void". -* Fix instantiating typedefs to bounds (#32114) -* preview-dart-2 implies strong-mode now and other preview-dart-2 fixes. -* Store method invocation arguments in summaries when needed for inference (partial fix for #32394) -* Fix top-level inference and implicit creation (#32397) -* Do not hint when only a responsive asset exists (#32250) -* Do not hint when using a deprecated parameter in the defining function - (#32468) -* Fix parsing of super expressions (#32393) -* Disable conflicting generics test in the task model (#32421) -* Change how we find analysis roots (#31343, #31344) -* Fix problem with AST re-writing interacting poorly with inference (#32342) -* Disallow if a class inconsistently implements a generic interface. -* Infer void for operator[]= return in task mode for DDC (#32241) -* Finish and improve mixin type inference in the analyzer (#32146, #32353, #32372) -* Many enhancements to getElementDeclarations() (#29510, #32495) -* Remove hint when there's no return from a Future and async method. -* Add a code range to ElementDeclaration (#29510) -* Many, many fasta parser changes and improvements. -* Add missing void annotation (#32161) -* Add more null-aware hints (#32239) -* Fix implicit new/const computation (#32221) -* Treat invocations on dynamic as unknown, except for return type of == (#32173) -* Fix crash in generic function type argument of unresolved class (#32162) -* Fix path formatting on windows (#32095) -* front_end implementation of mixin type inference (#31984) -* analysis_options no longer breaks some properties (#31345) - -## 0.31.2-alpha.0 - -* front_end handling of callable classes (#32064) -* Improve fasta parser error reporting. -* Check for unresolved imports to improve handling of optional new/const (#32150). -* Changes to front_end handling of callable classes. -* Normalize Windows drive letters to uppercase for analysis (#32095, #32042, #28895). -* Relax void errors: no error assigning void to void variable. -* Keep unresolved import/export directives for task based analysis - (dart-lang/angular#801). -* Promote `TOP_LEVEL_CYCLE` to an error. -* Code cleanups. - -## 0.31.1 - -* Update to reflect that `_InternalLinkedHashMap` is not a subtype of `HashMap` - in sdk 2.0.0-dev.22.0. - -## 0.31.0+1 - -* Update SDK constraint to require Dart v2-dev release. - -## 0.31.0 - -* **NOTE** This release was pulled from the package site due to an invalid SDK - constraint that was fixed in `0.31.0+1`. - -* A number of updates, including support for the new Function syntax. - -## 0.30.0-alpha.0 -* Changed the API for creating BazelWorkspace. It should now be constructed using BazelWorkspace.find(). Note that this might return `null` in the event that the given path is not part of a BazelWorkspace. -* Added an AST structure to support asserts in constructor initializers (AssertInitializer). AstVisitor classes must now implement visitAssertInitializer(). -* Changed the API for creating PartOfDirective. It now accepts a StringLiteral URI, to accommodate "part of" declarations with a URI string rather than a library name. -* Removed AST constructors. AST nodes should now be created using `astFactory`, located in `package:analyzer/dart/ast/standard_ast_factory.dart`. - -## 0.29.0-alpha.0 -* Removed `Element.docRange`. - -## 0.28.2-alpha.0 -* Corresponds with the analyzer/server in the `1.20.0-dev.1.0` SDK. - -## 0.28.0-alpha.2 -* Fixed PubSummaryManager linking when a listed package does not have the unlinked bundle. - -## 0.27.4-alpha.19 -* Added support for running the dev compiler in the browser. - -## 0.27.4-alpha.18 -* Support for references to operators in doc comments (#26929). - -## 0.27.4-alpha.17 -* Support for trailing commas in parameter and argument lists (#26647). -* Strong mode breaking change: can now infer generic type arguments from the constructor invocation arguments (#25220). - -## 0.27.4-alpha.16 -* (Internal) Corresponds with the analyzer/server in the `1.18.0-dev.4.0` SDK. - -## 0.27.4-alpha.9 -* Restore EmbedderUriResolver API. - -## 0.27.4-alpha.8 -* Ignore processing performance improvements. -* EmbedderUriResolver API updates. - -## 0.27.4 - -* Added support for 'analysis_options.yaml' files as an alternative to '.analysis_options' files. - -## 0.27.1 -* Moved the public and private API's for the element model into their proper places. -* Added back support for auto-processing of plugins. - -## 0.27.0 -* Support for DEP 37 (Assert with optional message). -* Lexical support for DEP 40 (Interface libraries). This does not include any semantic checking to ensure that the - implementation libraries are compatible with the interface library. -* Cleaned up the initialization of plugins. Clients are now required to initialize plugins, possibly using the utility - method AnalysisEngine.processRequiredPlugins(). -* Removed the old task model and code that supported it. None of the removed code was intended to be public API, but - might be in use anyway. -* Removed previously deprecated API's (marked with the @deprecated annotation). - -## 0.26.4 -* Options processing API updated to accept untyped options maps (#25126). - -## 0.26.3 -* (Internal) Support for `_embedder.yaml` discovery and processing. - -## 0.26.2 -* Add code generation utilities for use in both analyzer and analysis server. - -## 0.26.1+17 -* (Internal) Introduced context configuration logic (`configureContext()` extracted from server). - -## 0.26.1+16 -* (Internal) Options validation plugin API update. - -## 0.26.1+15 -* (Internal) Provisional options validation plugin API. - -## 0.26.1+13 -* (Internal) Plugin processing fixes. - -## 0.26.1+11 -* Fixes to address lint registry memory leaking. - -## 0.26.1+10 -* New `AnalysisContext` API for associating configuration data with contexts - (`setConfigurationData()` and `getConfigurationData()`). - -## 0.26.1+9 -* `OptionsProcessor` extension point API changed to pass associated - `AnalysisContext` instance into the `optionsProcessed` call-back. - -## 0.26.1+6 -* Provisional (internal) plugin manifest parsing. - -## 0.26.1+5 -* Plugin configuration `ErrorHandler` typedef API fix. - -## 0.26.1+4 -* Provisional (internal) support for plugin configuration via `.analysis_options`. - -## 0.26.1+2 - -* Extension point for WorkManagerFactory(s). -* Resolve enum documentation comments. -* Fix display of parameter lists in servers Element structure (issue 24194) -* Band-aid fix for issue #24191. - -## 0.26.1+1 - -* Removed a warning about importing unnamed libraries -* Fix handling of empty URIs in `.packages` files (issue 24126) - -## 0.26.1 - -* Fix line starts in multiline comments (issue 23919). -* Various small fixes to Windows path handling. -* Update LineInfo computation during incremental resolution. -* Make exclude list apply to contexts (issue 23941). -* Fix type propagation for asynchronous for-in statements. -* Fix ToStringVisitor for external functions (issue 23968). -* Fix sorting of compilation unit members. -* Add forwarding for DefaultFormalParameter metadata. -* Fix most implementations of UriResolver.restoreAbsolute. -* Disable dart2js hints by default. -* Support older SDKs (Dart 1.11). - -## 0.26.0 - -* Add hook for listening to implicitly analyzed files -* Add a PathFilter and AnalysisOptionsProvider utility classes to aid - clients in excluding files from analysis when directed to do so by an - options file. -* API change: `UriResolver.resolveUri(..)` now takes an optional `actualUri`. -* Change `ResolutionCopier.visitAwaitExpression` to copy *Type fields. -* Fix highlight range for missing enum constant in switch (issue 23904). -* Fix analyzer's treatment of `ClassName?.staticMember` to match spec. -* Implement DEP 34 (less restricted mixins). -* Fix some implementations of `UriResolver.resolveUri(..)` that did not - properly handle the new `actualUri` argument. - -## 0.25.2 - -* Requires Dart SDK 1.12-dev or greater -* Enable null-aware operators (DEP 9) by default. -* Generic method support in the element model. - -## 0.25.2-alpha.1 - -* `dart:sdk` extension `.sdkext` changed to `_sdkext` (to play nicer with pub). - -## 0.25.2-alpha.0 - -* Initial support for analyzing `dart:sdk` extensions from `.sdkext`. - -## 0.25.1 - -* (Internal) code reorganization to address analysis warnings due to SDK reorg. -* First steps towards `.packages` support. - -## 0.25.0 - -* Commandline interface moved to dedicated `analyzer_cli` package. Files moved: - * `bin/analyzer.dart` - * `lib/options.dart` - * `lib/src/analyzer_impl.dart` - * `lib/src/error_formatter.dart` -* Removed dependency on the `args` package. - -## 0.22.1 - -* Changes in the async/await support. - - -## 0.22.0 - - New API: - -* `Source.uri` added. - - Breaking changes: - -* `DartSdk.fromEncoding` replaced with `fromFileUri`. -* `Source.resolveRelative` replaced with `resolveRelativeUri`. - - - -
- typed_data | 1.3.1 -> 1.3.2 | transitive dev + + changelog_bubbler | 0.1.0 -> 0.1.0 +
- ## 1.3.2 - -* Added package topics to the pubspec file. -* Require Dart 2.17. - -## 1.3.1 - -* Switch to using `package:lints`. -* Populate the pubspec `repository` field. - -## 1.3.0 - -* Stable release for null safety. -* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release - guidelines. - -## 1.2.0 - -* Add typed queue classes such as `Uint8Queue`. These classes implement both - `Queue` and `List` with a highly-efficient typed-data-backed implementation. - Their `sublist()` methods also return typed data classes. -* Update min Dart SDK to `2.4.0`. - -## 1.1.6 - -* Set max SDK version to `<3.0.0`, and adjust other dependencies. - -## 1.1.5 - -* Undo unnecessary SDK version constraint tweak. - -## 1.1.4 - -* Expand the SDK version constraint to include `<2.0.0-dev.infinity`. - -## 1.1.3 - -* Fix all strong-mode warnings. - -## 1.1.2 - -* Fix a bug where `TypedDataBuffer.insertAll` could fail to insert some elements - of an `Iterable`. - -## 1.1.1 - -* Optimize `insertAll` with an `Iterable` argument and no end-point. - -## 1.1.0 - -* Add `start` and `end` parameters to the `addAll()` and `insertAll()` methods - for the typed data buffer classes. These allow efficient concatenation of - slices of existing typed data. - -* Make `addAll()` for typed data buffer classes more efficient for lists, - especially typed data lists. - -## 1.0.0 - -* ChangeLog starts here - -
- -
-
- vm_service | 11.5.0 -> 11.6.0 | transitive dev -
- ## 11.6.0 -- Update to version `4.7` of the spec. -- Add deprecation notice to `Stack.awaiterFrames`. -- Add deprecation notice to `FrameKind.kAsyncActivation`. - - -
- -
- - - + CHANGELOG.md did not contain changes + -
- github.com/dart-lang/pubspec_parse -
- pubspec_parse | ADDED | direct main -
- -
- - +## Changed Dependencies +
+No changed dependencies +
\ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b11ae88 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,61 @@ +# Contributing guide + + + +## Contribution Steps +1. Make sure you are up to date with `main` +1. Run all tests: `flutter test` +1. Set up an alias to run commands locally (see below for instructions) +1. Hack away! Test your changes locally, and add unit tests to cover everything +1. Bump the version in the pubspec.yaml +1. Commit your changes +1. Make your PR!!! `gh pr create --fill` + +## Run commands locally during development +``` +dart <-path to this repo->/bin/changelog_bubbler.dart --help +``` +example: +``` +dart /Users/micaiah.skolnick/Repos/changelog_bubbler/bin/changelog_bubbler.dart --help +``` + +Pro-tip: + +> You can create an alias to make it easier to develop locally. +--- + +### Mac: + +1. Add an alias to your bash profile (default is .zshrc) + + ``` + alias local_bubbler='dart /Users/micaiah.skolnick/Repos/changelog_bubbler/bin/changelog_bubbler.dart' + ``` +1. Open a new terminal window +--- + +### Windows: + +Add a function to your powershell profile. +1. Create a file named `profile.ps1` at your powershell directory. eg: `C:\Users\micaiah.skolnick\Documents\WindowsPowerShell\profile.ps1` +1. Add the following function to your profile. **Replace the path with the path to the repository on your machine + ``` + Function local_bubbler { + dart run C:\Users\micaiah.skolnick\Repos\changelog_bubbler/bin/changelog_bubbler.dart $args + } + ``` +1. Open a new Powershell window + +--- + +> Now you can run commands from anywhere like so: +``` +local_bubbler --help +``` + +### To test +General testing: +``` +flutter test +``` diff --git a/README.md b/README.md index b1b04ab..ac5a457 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -

UNDER DEVELOPMENT - NOT READY FOR USE

Changelog Bubbler


@@ -15,30 +14,26 @@ ## Overview -The goal of this package is to automate the process of creating a changelog diff for flutter and dart applications. This package not only gathers the changelog diff from the current package. It also analyzes every sub-package and bubbles up their changelogs as well. +The goal of this package is to automate the process of creating a changelog diff for flutter and dart applications. This package not only gathers the changelog diff from the current package. It also analyzes every changed sub-package and bubbles up their changelogs as well. ### How it Works -This package generates a single CHANGELOG_BUBBLES.md file which contains the changelog diff from this application and every depended on dart application. +This package generates a single CHANGELOG_BUBBLED.md file which contains the changelog diff from this application and every depended on dart application. This builder works as follows: -1. Read passed in args (ie.. ref to compare with current) +1. Read passed in args (ie.. see args by running `dart pub run changelog_bubbler --help`) 1. Copy source Repo into temp folder and check out at specified ref 1. Gather info of repo in states current and previous 1. Run pub get 1. Read pubspec lock 1. Build dep list based on pubspec lock and pub_cache 1. Store path to pub_cache in dependency class for later reference -1. Build release notes - 1. Private Hosted - Direct - 1. Private Hosted - Transitive - 1. pub.dev - Direct - 1. pub.dev - Transitive -1. Release note section building - 1. Only changed deps +1. Build list of changed dependencies + 1. Group by Host URL (ie.. pub.dev, git, or hosted refs) + 1. Only gather changed deps 1. Print: 1. name 1.0.0 -> 2.0.0 - 1. Changelog new lines + 1. Changelog diff from package 1. Create a file with the information gathered above @@ -59,11 +54,9 @@ This builder works as follows: 1. `CHANGELOG_BUBBLED.g.md` will be generated with content: ``` -# Bubbled Changelog - Example app -## Hosted - Direct +## pub.dev my_app_core 1.0.0 - 1.1.0 @@ -102,7 +95,7 @@ If you are using this in Github Actions, you will need to set the fetch-depth of ### Previous Ref By default the changelog will be generated based on a diff between the current git state and the previous tag. -To specify your own ref, pass a flag named `previous-ref` with your desired git ref. +To specify your own ref to compare with the current state, pass a flag named `previous-ref` with your desired git ref. example: ``` @@ -121,9 +114,21 @@ example: dart pub run changelog_bubbler --output MY_COOL_CHANGELOG_NAME.md ``` +### Templates +All output is built based on templates found in the [Template Folder][template_folder]. + +Any of the templates can be overriden by passing a path option. + +example: +``` +dart pub run changelog_bubbler --changelog-template-path '/Users/micaiah.skolnick/Repos/alkami/changelog_bubbler/asset_test/changelog_template.html' +``` + +Run `dart pub run changelog_bubbler --help` to see a list of all possible path overrides. ## Maintainers - [Micaiah Skolnick](https://github.com/m-skolnick) -[example_app_output]: https://github.com/m-skolnick/changelog_bubbler/blob/main/example/my_output_file.md \ No newline at end of file +[example_app_output]: https://github.com/m-skolnick/changelog_bubbler/blob/main/example/my_output_file.md +[template_folder]: https://github.com/m-skolnick/changelog_bubbler/blob/main/template/ \ No newline at end of file diff --git a/bin/changelog_bubbler.dart b/bin/changelog_bubbler.dart index e558882..6d34530 100644 --- a/bin/changelog_bubbler.dart +++ b/bin/changelog_bubbler.dart @@ -13,5 +13,6 @@ Future main(List args) async { /// exited already. This is useful to prevent Future chains from proceeding /// after you've decided to exit. Future _flushThenExit(int status) { - return Future.wait([stdout.close(), stderr.close()]).then((_) => exit(status)); + return Future.wait([stdout.close(), stderr.close()]) + .then((_) => exit(status)); } diff --git a/lib/src/change_manager.dart b/lib/src/change_manager.dart new file mode 100644 index 0000000..a1ddcb9 --- /dev/null +++ b/lib/src/change_manager.dart @@ -0,0 +1,70 @@ +import 'package:changelog_bubbler/src/dependency_pair.dart'; +import 'package:changelog_bubbler/src/dependency_parser.dart'; +import 'package:changelog_bubbler/src/dependency_type.dart'; +import 'package:collection/collection.dart'; + +class ChangeManager { + /// Holds the parsed dependencies for the repo in the current state + final DependencyParser current; + + /// Holds the parsed dependencies for the repo in the previous state + final DependencyParser previous; + + /// All of the dependencies that have changed between the previous and current version + late final List changedDeps; + + /// Changed deps grouped by hosted url + late final Map> groups; + + ChangeManager({ + required this.current, + required this.previous, + }) { + changedDeps = _getChangedDeps(); + groups = _buildGroups(); + } + + List _getChangedDeps() { + final allDeps = {...current.dependencies, ...previous.dependencies}; + + final changedDeps = allDeps.values.where((e) => + previous.dependencies[e.name]?.sameVersion(e) != true || + current.dependencies[e.name]?.sameVersion(e) != true); + + final changedDepNames = changedDeps.map((e) => e.name).toList(); + final sortedChangedDeps = changedDepNames..sort((a, b) => a.compareTo(b)); + + return sortedChangedDeps + .map((e) => DependencyPair( + current: current.dependencies[e], + previous: previous.dependencies[e], + )) + .toList(); + } + + Map> _buildGroups() { + final Map> groups = {}; + + // Groups are built by section + // Each section will be for a separate hosted location + // Gather the unique urls for hosted dependencies + final urlSet = changedDeps.map((e) => e.trimmedUrl).whereNotNull().toSet(); + + // Loop through the groups and locate the pairs of previous and current dep + // which belong to that group + for (final groupUrl in urlSet) { + final depsInGroup = changedDeps.where((e) => e.trimmedUrl == groupUrl); + + // Inside of the group, sort dependencies by dependency type + for (final dependencyType in DependencyType.sorted) { + final depsOfDepType = + depsInGroup.where((e) => e.dependencyType == dependencyType); + + for (final dep in depsOfDepType) { + groups[groupUrl] = (groups[groupUrl] ?? [])..add(dep); + } + } + } + return groups; + } +} diff --git a/lib/src/change_type.dart b/lib/src/change_type.dart new file mode 100644 index 0000000..f583cbf --- /dev/null +++ b/lib/src/change_type.dart @@ -0,0 +1,14 @@ +enum ChangeType { + added('ADDED'), + removed('REMOVED'), + updated('UPDATED'); + + const ChangeType(this.name); + final String name; + + static const sorted = [ + ChangeType.added, + ChangeType.removed, + ChangeType.updated, + ]; +} diff --git a/lib/src/changelog_bubbler.dart b/lib/src/changelog_bubbler.dart index 43640cf..8eb17b2 100644 --- a/lib/src/changelog_bubbler.dart +++ b/lib/src/changelog_bubbler.dart @@ -1,12 +1,16 @@ +import 'dart:async'; import 'dart:io'; import 'package:args/args.dart'; import 'package:args/command_runner.dart'; +import 'package:changelog_bubbler/src/bubbler_shell.dart'; +import 'package:changelog_bubbler/src/change_manager.dart'; +import 'package:changelog_bubbler/src/changelog_builder.dart'; import 'package:changelog_bubbler/src/dependency_parser.dart'; -import 'package:changelog_bubbler/src/diff_builder.dart'; import 'package:changelog_bubbler/src/global_dependencies.dart'; +import 'package:changelog_bubbler/src/logger.dart'; import 'package:changelog_bubbler/src/repository_preparer.dart'; -import 'package:io/ansi.dart'; +import 'package:changelog_bubbler/src/template_manager.dart'; import 'package:io/io.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as p; @@ -32,6 +36,31 @@ class ChangelogBubbler extends CommandRunner { help: 'The name of the changelog to search for', defaultsTo: 'CHANGELOG.md', ); + argParser.addOption( + 'changelog-template-path', + help: 'The path of the root changelog template', + defaultsTo: 'changelog_template.html', + ); + argParser.addOption( + 'dependency-group-template-path', + help: 'The path of the root changelog template', + defaultsTo: 'dependency_group_template.html', + ); + argParser.addOption( + 'dependency-changed-template-path', + help: 'The path of the root changelog template', + defaultsTo: 'dependency_changed_template.html', + ); + argParser.addOption( + 'dependency-added-or-removed-template-path', + help: 'The path of the root changelog template', + defaultsTo: 'dependency_added_or_removed_template.html', + ); + argParser.addOption( + 'no-changed-dependencies-template-path', + help: 'The path of the root changelog template', + defaultsTo: 'no_changed_dependencies_template.html', + ); argParser.addFlag( 'dev', help: 'Include dev dependencies in output', @@ -62,21 +91,41 @@ class ChangelogBubbler extends CommandRunner { return ExitCode.usage.code; } // Define the tempDir where this repo will be copied to and set to the state to compare - final tempDir = Directory.systemTemp.createTempSync('temp_changelog_bubbler_dir'); + final tempDir = + Directory.systemTemp.createTempSync('temp_changelog_bubbler_dir'); + final stopwatch = Stopwatch()..start(); try { final prevousRefArg = argResults['previous-ref'] as String?; final changelogName = argResults['changelog-name'] as String; final outputArg = argResults['output'] as String; final shouldIncludeDevArg = argResults['dev'] as bool; final shouldIncludeTransitiveArg = argResults['transitive'] as bool; + final changelogTemplatePath = + argResults['changelog-template-path'] as String; + final dependencyGroupTemplatePath = + argResults['dependency-group-template-path'] as String; + final dependencyChangedTemplatePath = + argResults['dependency-changed-template-path'] as String; + final dependencyAddedOrRemovedTemplatePath = + argResults['dependency-added-or-removed-template-path'] as String; + final noChangedDependenciesTemplate = + argResults['no-changed-dependencies-template-path'] as String; - print('Ensuring the working directory is a dart git repo...'); + var prompt = 'Ensuring the working directory is a git repo'; + Logger.progressStart(prompt); await validateWorkingDir(); + Logger.progressSuccess(prompt); + + prompt = 'Running pub get'; + Logger.progressStart(prompt); + await runPubGet(); + Logger.progressSuccess(prompt); - print('Copying the current repo to a tempDir...'); + prompt = 'Copying the current repo to a tempDir'; + Logger.progressStart(prompt); await copyPath(workingDir, tempDir.path); + Logger.progressSuccess(prompt); - print('In temp dir: Cleaning git state, checking out previous ref, running a pub get...'); await RepositoryPreparer( repoPath: tempDir.path, passedRef: prevousRefArg, @@ -84,28 +133,48 @@ class ChangelogBubbler extends CommandRunner { final parserPrevious = DependencyParser(repoPath: tempDir.path); final parserCurrent = DependencyParser(repoPath: workingDir); - print('In temp dir: Parsing dependencies from pubspec.lock'); + + prompt = 'Copying the current repo to a tempDir'; + Logger.progressStart(prompt); + prompt = 'In temp dir: Parsing dependencies from pubspec.lock'; parserPrevious.parseDependencies( includeTransitive: shouldIncludeTransitiveArg, includeDev: shouldIncludeDevArg, ); - print('In current: Parsing dependencies from pubspec.lock...'); + Logger.progressSuccess(prompt); + + prompt = 'In current dir: Parsing dependencies from pubspec.lock'; + Logger.progressStart(prompt); parserCurrent.parseDependencies( includeTransitive: shouldIncludeTransitiveArg, includeDev: shouldIncludeDevArg, ); + Logger.progressSuccess(prompt); - print('Building diff...'); - final diff = await DiffBuilder( - previous: parserPrevious, - current: parserCurrent, + prompt = 'Building diff'; + Logger.progressStart(prompt); + final diff = await ChangelogBuilder( changelogName: changelogName, - ).buildDiff(); + changeManager: ChangeManager( + previous: parserPrevious, + current: parserCurrent, + ), + changelogTemplate: TemplateManager(changelogTemplatePath), + depGroupTemplate: TemplateManager(dependencyGroupTemplatePath), + depChangedTemplate: TemplateManager(dependencyChangedTemplatePath), + depAddedOrRemovedTemplate: + TemplateManager(dependencyAddedOrRemovedTemplatePath), + noChangedDependenciesTemplate: + TemplateManager(noChangedDependenciesTemplate), + ).buildChangelogFromTemplates(); + Logger.progressSuccess(prompt); - print('Writing diff to file ...'); + prompt = 'Writing diff to file'; + Logger.progressStart(prompt); final outputFile = File(outputArg); outputFile.writeAsStringSync(diff); - print('${lightGreen.wrap('✓')} Diff written to ${outputFile.absolute}'); + Logger.progressSuccess(prompt); + Logger.progressSuccess('Diff written to ${outputFile.absolute}'); } on UsageException catch (e) { print(e.message); print(''); @@ -117,27 +186,44 @@ class ChangelogBubbler extends CommandRunner { return ExitCode.unavailable.code; } finally { - print('Deleting temp dir...'); + final prompt = 'Deleting temp dir'; + Logger.progressStart(prompt); tempDir.deleteSync(recursive: true); + Logger.progressSuccess(prompt); + print('(${stopwatch.elapsed.inSeconds}s)'); } return ExitCode.success.code; } - /// Ensure the working directory is a dart git repo + /// Ensure the working directory is a git repo /// - /// * Check if current dir is a dart project - /// * Error out of it is not a git dir and does not contain a pubspec.yaml - /// * We don't want users to accidentally run this in a folder that doesn't contain a flutter project + /// * Error out of it is not a git dir @visibleForTesting Future validateWorkingDir() async { - final pubspecYamlExists = File(p.join(workingDir, 'pubspec.yaml')).existsSync(); - if (!pubspecYamlExists) { - throw (Exception('pubspec.yaml not found. Program must be run from a dart repository')); - } final isGitDir = Directory(p.join(workingDir, '.git')).existsSync(); if (!isGitDir) { - throw (Exception('.git folder found. Program must be run from a git repository')); + throw (Exception( + '.git folder not found. Program must be run from a git repository')); + } + } + + /// Run a pub get to make sure pubspec.lock exists + /// This also ensures the working directory is a dart repo + /// + /// * We don't want users to accidentally run this in a folder that doesn't contain a dart project + @visibleForTesting + Future runPubGet() async { + final shell = getDep(); + + try { + await shell.run( + 'dart pub get', + workingDir: workingDir, + ); + } catch (e) { + throw (Exception( + '`dart pub get` errored out. Program must be run from the root of a dart project. Error: $e')); } } } diff --git a/lib/src/changelog_builder.dart b/lib/src/changelog_builder.dart new file mode 100644 index 0000000..8aa7c02 --- /dev/null +++ b/lib/src/changelog_builder.dart @@ -0,0 +1,122 @@ +import 'dart:io'; + +import 'package:changelog_bubbler/src/change_manager.dart'; +import 'package:changelog_bubbler/src/dependency_pair.dart'; +import 'package:changelog_bubbler/src/template_manager.dart'; +import 'package:path/path.dart' as p; + +class ChangelogBuilder { +// Manages the differences between the previous dependencies and current + final ChangeManager changeManager; + + /// The name of the changelog we should be searching for + /// This can be a value passed by the user. Check CLI input for defaults. + final String changelogName; + + /// The top level template + final TemplateManager changelogTemplate; + + /// Second level template used for dependency groups + final TemplateManager depGroupTemplate; + + /// Lowest level template used for templating a changed dependency + final TemplateManager depChangedTemplate; + + /// Lowest level template used for templating an added or deleted dependency + final TemplateManager depAddedOrRemovedTemplate; + + /// Used when the app update had no dependency changes + final TemplateManager noChangedDependenciesTemplate; + + ChangelogBuilder({ + required this.changeManager, + required this.changelogName, + required this.changelogTemplate, + required this.depGroupTemplate, + required this.depChangedTemplate, + required this.depAddedOrRemovedTemplate, + required this.noChangedDependenciesTemplate, + }); + + Future buildChangelogFromTemplates() async { + return changelogTemplate.replaceAll({ + '{{root_package_name}}': changeManager.previous.pubspec.name, + '{{root_previous_version}}': + changeManager.previous.pubspec.version.toString(), + '{{root_current_version}}': + changeManager.current.pubspec.version.toString(), + '{{root_changelog_diff}}': _getChangelogDiff( + currentPath: changeManager.current.repoPath, + previousPath: changeManager.previous.repoPath, + ), + '{{dependency_groups}}': _buildGroupsFromTemplate(), + }); + } + + String _buildGroupsFromTemplate() { + final stringBuffer = StringBuffer(); + + if (changeManager.groups.isEmpty) { + return noChangedDependenciesTemplate.unalteredTemplate; + } + + for (final group in changeManager.groups.entries) { + final dependencyListBuffer = StringBuffer(); + for (final depPair in group.value) { + dependencyListBuffer.write(_buildInvidualDepFromTemplate(depPair)); + } + final substitutedTemplate = depGroupTemplate.replaceAll({ + '{{group_name}}': group.key, + '{{changed_dependencies}}': dependencyListBuffer.toString(), + }); + + stringBuffer.write(substitutedTemplate); + } + + return stringBuffer.toString(); + } + + String _buildInvidualDepFromTemplate(DependencyPair depPair) { + final current = depPair.current; + final previous = depPair.previous; + + if (current != null && previous != null) { + return depChangedTemplate.replaceAll({ + '{{package_name}}': depPair.name, + '{{previous_version}}': previous.version.toString(), + '{{current_version}}': current.version.toString(), + '{{dependency_type}}': depPair.dependencyType.name, + '{{changelog_diff}}': _getChangelogDiff( + previousPath: previous.getPubCachePath(), + currentPath: current.getPubCachePath(), + ), + }); + } + + return depAddedOrRemovedTemplate.replaceAll({ + '{{package_name}}': depPair.name, + '{{change_type}}': depPair.changeType.name, + '{{dependency_type}}': depPair.dependencyType.name, + }); + } + + String _getChangelogDiff({ + required String previousPath, + required String currentPath, + }) { + final previousChangelog = File(p.join(previousPath, changelogName)); + final currentChangelog = File(p.join(currentPath, changelogName)); + + if (!previousChangelog.existsSync() || !currentChangelog.existsSync()) { + return '$changelogName not found'; + } + final previousString = previousChangelog.readAsStringSync(); + final currentString = currentChangelog.readAsStringSync(); + final diff = currentString.replaceFirst(previousString, ''); + if (diff.isEmpty) { + return '$changelogName did not contain changes'; + } + + return diff; + } +} diff --git a/lib/src/dependency_pair.dart b/lib/src/dependency_pair.dart new file mode 100644 index 0000000..a4e1f26 --- /dev/null +++ b/lib/src/dependency_pair.dart @@ -0,0 +1,29 @@ +import 'package:changelog_bubbler/src/change_type.dart'; +import 'package:changelog_bubbler/src/dependency_type.dart'; +import 'package:changelog_bubbler/src/package_wrapper.dart'; + +class DependencyPair { + final PackageWrapper? previous; + final PackageWrapper? current; + + DependencyPair({ + this.previous, + this.current, + }) : assert(previous != null || current != null, + 'Either previous or current must not be null'); + + ChangeType get changeType { + if (previous == null) { + return ChangeType.added; + } + if (current == null) { + return ChangeType.removed; + } + return ChangeType.updated; + } + + String get name => (previous?.name ?? current?.name)!; + String? get trimmedUrl => previous?.trimmedUrl ?? current?.trimmedUrl; + DependencyType get dependencyType => + (previous?.dependencyType ?? current?.dependencyType)!; +} diff --git a/lib/src/dependency_parser.dart b/lib/src/dependency_parser.dart index e4cd110..b4c7331 100644 --- a/lib/src/dependency_parser.dart +++ b/lib/src/dependency_parser.dart @@ -17,7 +17,8 @@ class DependencyParser { final _shell = getDep(); DependencyParser({required this.repoPath}) { - final pubspecString = File(p.join(repoPath, 'pubspec.yaml')).readAsStringSync(); + final pubspecString = + File(p.join(repoPath, 'pubspec.yaml')).readAsStringSync(); pubspec = Pubspec.parse(pubspecString); } @@ -26,44 +27,52 @@ class DependencyParser { required bool includeTransitive, }) { // Get all of the dependencies from the pubspec.lock - final lockString = File(p.join(repoPath, 'pubspec.lock')).readAsStringSync(); + final lockString = + File(p.join(repoPath, 'pubspec.lock')).readAsStringSync(); final lockfile = PubspecLock.parse(lockString); - final allDeps = lockfile.packages.map((key, value) => MapEntry(key, PackageWrapper(key, value))); + final devDeps = _isolateDevDeps(lockfile.packages.keys); - final devDeps = _isolateDevDeps(allDeps.keys); - var filteredDeps = allDeps; + final wrappedDeps = lockfile.packages.map((key, value) => MapEntry( + key, + PackageWrapper( + key, + value, + _determineDependencyType(key, value, devDeps), + ))); + + var filteredDeps = wrappedDeps; if (!includeDev) { filteredDeps = _filterDevDeps(filteredDeps, devDeps); } if (!includeTransitive) { filteredDeps = _filterTransitiveDeps(filteredDeps); } - - filteredDeps = _labelDependencyTypes(filteredDeps, devDeps); dependencies = filteredDeps; } - Map _filterDevDeps(Map deps, Set devDeps) { + Map _filterDevDeps( + Map deps, Set devDeps) { return {...deps}..removeWhere((key, value) => devDeps.contains(key)); } - Map _filterTransitiveDeps(Map deps) { - return {...deps}..removeWhere((key, value) => value.package.dependency == 'transitive'); + Map _filterTransitiveDeps( + Map deps) { + return {...deps} + ..removeWhere((key, value) => value.package.dependency == 'transitive'); } - Map _labelDependencyTypes(Map deps, Set devDeps) { - return deps.map((key, value) { - if (value.package.dependency == 'transitive') { - if (devDeps.contains(key)) { - return MapEntry(key, value..dependencyType = DependencyType.transitiveDev); - } - return MapEntry(key, value..dependencyType = DependencyType.transitiveMain); - } - if (devDeps.contains(key)) { - return MapEntry(key, value..dependencyType = DependencyType.directDev); + DependencyType _determineDependencyType( + String name, Package package, Set devDepNames) { + if (package.dependency == 'transitive') { + if (devDepNames.contains(name)) { + return DependencyType.transitiveDev; } - return MapEntry(key, value..dependencyType = DependencyType.directMain); - }); + return DependencyType.transitiveMain; + } + if (devDepNames.contains(name)) { + return DependencyType.directDev; + } + return DependencyType.directMain; } /// The pubspec.lock does not distinguish "transitive dev" from "transitive main" they are all labeled "transitive" diff --git a/lib/src/diff_builder.dart b/lib/src/diff_builder.dart deleted file mode 100644 index 1929cb5..0000000 --- a/lib/src/diff_builder.dart +++ /dev/null @@ -1,227 +0,0 @@ -import 'dart:io'; - -import 'package:changelog_bubbler/src/dependency_parser.dart'; -import 'package:changelog_bubbler/src/dependency_type.dart'; -import 'package:changelog_bubbler/src/package_wrapper.dart'; -import 'package:collection/collection.dart'; -import 'package:path/path.dart' as p; - -class DiffBuilder { - /// Holds the parsed dependencies for the repo in the current state - final DependencyParser current; - - /// Holds the parsed dependencies for the repo in the previous state - final DependencyParser previous; - - /// The name of the changelog we should be searching for - /// This can be a value passed by the user. Check CLI input for defaults. - final String changelogName; - - DiffBuilder({ - required this.previous, - required this.current, - required this.changelogName, - }); - - Future buildDiff() async { - return _fullOutputStr( - mainApp: _buildMainAppSection(), - dependencyGroups: _buildGroups(), - ); - } - - String _buildGroups() { - // Find the packages that have changed - final changedDeps = {...current.dependencies, ...previous.dependencies}.entries.where((e) { - return previous.dependencies[e.key]?.sameVersion(e.value) != true || - current.dependencies[e.key]?.sameVersion(e.value) != true; - }); - final sortedDeps = changedDeps.toList()..sort((a, b) => a.key.compareTo(b.key)); - // We will build the diff by section - // Each section will be for a separate hosted location - // Gather the unique urls for hosted dependencies - final urlSet = sortedDeps.map((e) => e.value.trimmedUrl).whereNotNull().toSet(); - - final groupsBySection = StringBuffer(); - for (final groupUrl in urlSet) { - final depsInGroup = sortedDeps.where((e) => e.value.trimmedUrl == groupUrl); - if (depsInGroup.isEmpty) { - continue; - } - final groupBuffer = StringBuffer(); - for (final dependencyType in DependencyType.sorted) { - final depsOfDepType = depsInGroup.where((e) => e.value.dependencyType == dependencyType); - if (depsOfDepType.isEmpty) { - continue; - } - for (final dep in depsOfDepType) { - final previousDep = previous.dependencies.entries.firstWhereOrNull((e) => e.key == dep.key); - final currentDep = current.dependencies.entries.firstWhereOrNull((e) => e.key == dep.key); - - groupBuffer.write(_buildPackageDiff( - previous: previousDep, - current: currentDep, - )); - } - } - groupsBySection.write( - _groupStr( - groupName: groupUrl, - packagesInGroup: groupBuffer.toString(), - ), - ); - } - - if (groupsBySection.isEmpty) { - return _emptyDependencyStr(); - } - - return groupsBySection.toString(); - } - - String _buildMainAppSection() { - return _mainPackageDiffStr( - packageName: previous.pubspec.name, - previousVersion: previous.pubspec.version.toString(), - currentVersion: current.pubspec.version.toString(), - changelogDiff: _getChangelogDiff( - currentPath: current.repoPath, - previousPath: previous.repoPath, - ), - ); - } - - String _buildPackageDiff({ - required MapEntry? previous, - required MapEntry? current, - }) { - assert(previous != null || current != null, 'Either previous or current must not be null'); - if (previous == null) { - return _depAddedOrRemovedStr( - packageName: current!.key, - dependencyType: current.value.dependencyType.name, - changeType: 'ADDED', - ); - } - if (current == null) { - return _depAddedOrRemovedStr( - packageName: previous.key, - dependencyType: previous.value.dependencyType.name, - changeType: 'REMOVED', - ); - } - - return _depDiffStr( - packageName: previous.key, - previousVersion: previous.value.version.toString(), - currentVersion: current.value.version.toString(), - dependencyType: current.value.dependencyType.name, - changelogDiff: _getChangelogDiff( - previousPath: previous.value.getPubCachePath(), - currentPath: current.value.getPubCachePath(), - ), - ); - } - - String _getChangelogDiff({ - required String previousPath, - required String currentPath, - }) { - final previousChangelog = File(p.join(previousPath, changelogName)); - final currentChangelog = File(p.join(currentPath, changelogName)); - - if (!previousChangelog.existsSync() || !currentChangelog.existsSync()) { - return '$changelogName not found'; - } - final previousString = previousChangelog.readAsStringSync(); - final currentString = currentChangelog.readAsStringSync(); - final diff = currentString.replaceFirst(previousString, ''); - if (diff.isEmpty) { - return '$changelogName did not contain changes'; - } - - return diff; - } - - String _fullOutputStr({ - required String mainApp, - required String dependencyGroups, - }) { - return ''' -# Bubbled Changelog - -## This app -$mainApp - -## Changed Dependencies -$dependencyGroups -'''; - } - - String _groupStr({ - required String groupName, - required String packagesInGroup, - }) { - return _collapsibleStr( - header: groupName, - body: packagesInGroup, - ); - } - - String _emptyDependencyStr() { - return _paddedDivStr(body: 'No changed dependencies'); - } - - String _mainPackageDiffStr({ - required String packageName, - required String previousVersion, - required String currentVersion, - required String changelogDiff, - }) { - return ''' -$packageName | $previousVersion -> $currentVersion -${_paddedDivStr(body: changelogDiff)} -'''; - } - - String _depDiffStr({ - required String packageName, - required String previousVersion, - required String currentVersion, - required String dependencyType, - required String changelogDiff, - }) { - return _collapsibleStr( - header: '$packageName | $previousVersion -> $currentVersion | $dependencyType', - body: changelogDiff, - ); - } - - String _depAddedOrRemovedStr({ - required String packageName, - required String changeType, - required String dependencyType, - }) { - return '$packageName | $changeType | $dependencyType'; - } - - String _collapsibleStr({ - required String header, - required String body, - }) { - return ''' -
- $header - ${_paddedDivStr(body: body)} -
-'''; - } - - String _paddedDivStr({required String body}) { - return ''' -
- $body -
-'''; - } -} diff --git a/lib/src/logger.dart b/lib/src/logger.dart new file mode 100644 index 0000000..69265bd --- /dev/null +++ b/lib/src/logger.dart @@ -0,0 +1,15 @@ +import 'dart:io'; + +import 'package:io/ansi.dart'; + +class Logger { + static final _greenCheck = '${lightGreen.wrap('✓')}'; + + static void progressStart(String prompt) { + stdout.write('$prompt...'); + } + + static void progressSuccess(String prompt) { + stdout.write('\r$_greenCheck $prompt \n'); + } +} diff --git a/lib/src/package_wrapper.dart b/lib/src/package_wrapper.dart index 35c45ff..0709096 100644 --- a/lib/src/package_wrapper.dart +++ b/lib/src/package_wrapper.dart @@ -1,19 +1,21 @@ import 'package:changelog_bubbler/src/dependency_type.dart'; import 'package:changelog_bubbler/src/global_dependencies.dart'; import 'package:changelog_bubbler/src/platform_wrapper.dart'; +import 'package:meta/meta.dart'; import 'package:pubspec_lock_parse/pubspec_lock_parse.dart'; import 'package:path/path.dart' as p; class PackageWrapper { final Package package; final String name; - late final DependencyType dependencyType; + final DependencyType dependencyType; - PackageWrapper(this.name, this.package); + PackageWrapper(this.name, this.package, this.dependencyType); String get version { if (package.description is GitPackageDescription) { - final resolvedRef = (package.description as GitPackageDescription).resolvedRef; + final resolvedRef = + (package.description as GitPackageDescription).resolvedRef; return resolvedRef.substring(0, 7); } @@ -33,7 +35,8 @@ class PackageWrapper { path = p.join(path, 'hosted', formattedUrl, '$name-${package.version}'); } if (package.description is GitPackageDescription) { - final resolvedRef = (package.description as GitPackageDescription).resolvedRef; + final resolvedRef = + (package.description as GitPackageDescription).resolvedRef; path = p.join(path, 'git', '$name-$resolvedRef'); } @@ -42,14 +45,16 @@ class PackageWrapper { String? get trimmedUrl { final scheme = 'https://'; - final url = _url; - if (url?.startsWith(scheme) == true) { - return url?.replaceFirst(scheme, ''); + // ignore: no_leading_underscores_for_local_identifiers + final _url = url; + if (_url?.startsWith(scheme) == true) { + return _url?.replaceFirst(scheme, ''); } - return url; + return _url; } - String? get _url { + @visibleForTesting + String? get url { if (package.description is HostedPackageDescription) { return (package.description as HostedPackageDescription).url; } diff --git a/lib/src/platform_wrapper.dart b/lib/src/platform_wrapper.dart index 3e62625..381deb1 100644 --- a/lib/src/platform_wrapper.dart +++ b/lib/src/platform_wrapper.dart @@ -1,3 +1,5 @@ +// coverage:ignore-file + import 'dart:io'; class PlatformWrapper { diff --git a/lib/src/repository_preparer.dart b/lib/src/repository_preparer.dart index 7048396..b830e28 100644 --- a/lib/src/repository_preparer.dart +++ b/lib/src/repository_preparer.dart @@ -1,3 +1,4 @@ +import 'package:changelog_bubbler/src/logger.dart'; import 'package:process_run/process_run.dart'; import 'package:changelog_bubbler/src/bubbler_shell.dart'; @@ -21,9 +22,20 @@ class RepositoryPreparer { /// * Check out ref /// * Get dependencies Future prepareTempRepo() async { + var prompt = 'In temp dir: Cleaning git state'; + Logger.progressStart(prompt); await _cleanGitState(); + Logger.progressSuccess(prompt); + + prompt = 'In temp dir: Checking out previous ref'; + Logger.progressStart(prompt); await _checkOutRef(); + Logger.progressSuccess(prompt); + + prompt = 'In temp dir: Running a pub get'; + Logger.progressStart(prompt); await _getDependencies(); + Logger.progressSuccess(prompt); } Future _cleanGitState() async { @@ -45,7 +57,8 @@ class RepositoryPreparer { Future _checkOutRef() async { final shell = getDep(); - final ref = passedRef ?? await _getPreviousTag() ?? await _getPreviousCommit(); + final ref = + passedRef ?? await _getPreviousTag() ?? await _getPreviousCommit(); await shell.run( 'git checkout $ref', diff --git a/lib/src/template_manager.dart b/lib/src/template_manager.dart new file mode 100644 index 0000000..b6cb8e4 --- /dev/null +++ b/lib/src/template_manager.dart @@ -0,0 +1,37 @@ +import 'dart:io'; +import 'package:path/path.dart' as p; + +class TemplateManager { + final String filePath; + String? _unalteredTemplate; + String get unalteredTemplate { + if (_unalteredTemplate != null) { + return _unalteredTemplate!; + } + var path = ''; + // If the file path is absolute, we assume the user passed in a path override + if (p.isAbsolute(filePath)) { + path = filePath; + } else { + // Here we assume the path to the template is the default + // So we do some manipulation to resolve the uri to the asset folder + // inside the changelog_bubbler package + final basePackagePath = File(Platform.script.toFilePath()).parent.parent; + path = p.join(basePackagePath.path, 'template', filePath); + } + final templateFile = File(path); + return _unalteredTemplate ??= templateFile.readAsStringSync(); + } + + TemplateManager(this.filePath, {String? templateForTesting}) + : _unalteredTemplate = templateForTesting; + + String replaceAll(Map replacements) { + var substitutedTemplate = unalteredTemplate; + for (final replacement in replacements.entries) { + substitutedTemplate = + substitutedTemplate.replaceFirst(replacement.key, replacement.value); + } + return substitutedTemplate; + } +} diff --git a/pubspec.lock b/pubspec.lock index 40df3f0..d2574b0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + http: + dependency: transitive + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" http_multi_server: dependency: transitive description: @@ -233,6 +241,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + oauth2: + dependency: transitive + description: + name: oauth2 + sha256: "1e8376c222651904caf7785fd2fa01b1e2be608c94bec842a94e116deca88f13" + url: "https://pub.dev" + source: hosted + version: "2.0.1" package_config: dependency: transitive description: @@ -265,6 +281,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.0" + pub_api_client: + dependency: "direct dev" + description: + name: pub_api_client + sha256: d4bc6c9ec778da1a79675eab41bde456b392973216acd783156afaee69230e22 + url: "https://pub.dev" + source: hosted + version: "2.4.0" pub_semver: dependency: "direct main" description: @@ -273,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pubspec: + dependency: transitive + description: + name: pubspec + sha256: f534a50a2b4d48dc3bc0ec147c8bd7c304280fff23b153f3f11803c4d49d927e + url: "https://pub.dev" + source: hosted + version: "2.3.0" pubspec_lock_parse: dependency: "direct main" description: @@ -289,6 +321,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" shelf: dependency: transitive description: @@ -417,14 +457,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" - test_process: - dependency: "direct dev" - description: - name: test_process - sha256: b0e6702f58272d459d5b80b88696483f86eac230dab05ecf73d0662e305d005e - url: "https://pub.dev" - source: hosted - version: "2.0.3" typed_data: dependency: transitive description: @@ -433,6 +465,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uri: + dependency: transitive + description: + name: uri + sha256: "889eea21e953187c6099802b7b4cf5219ba8f3518f604a1033064d45b1b8268a" + url: "https://pub.dev" + source: hosted + version: "1.0.0" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 487ff0e..bce1d67 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: changelog_bubbler version: 0.1.0 -description: Compiles changelogs from this package and every sub-package between specified refs +description: Compiles changelogs from this package and every sub-package (between specified refs) repository: https://github.com/m-skolnick/changelog_bubbler.dart environment: sdk: '>=2.18.0 <3.0.0' @@ -24,9 +24,9 @@ dependencies: dev_dependencies: lints: ^2.0.0 mocktail: ^0.3.0 + pub_api_client: ^2.4.0 test: ^1.24.2 test_descriptor: ^2.0.0 - test_process: ^2.0.0 executables: changelog_bubbler: changelog_bubbler \ No newline at end of file diff --git a/template/changelog_template.html b/template/changelog_template.html new file mode 100644 index 0000000..d33ead2 --- /dev/null +++ b/template/changelog_template.html @@ -0,0 +1,11 @@ +
+ + {{root_package_name}} | {{root_previous_version}} -> {{root_current_version}} + +
+ {{root_changelog_diff}} +
+
+ +## Changed Dependencies +{{dependency_groups}} \ No newline at end of file diff --git a/template/dependency_added_or_removed_template.html b/template/dependency_added_or_removed_template.html new file mode 100644 index 0000000..cd1e262 --- /dev/null +++ b/template/dependency_added_or_removed_template.html @@ -0,0 +1 @@ +{{package_name}} | {{change_type}} | {{dependency_type}} \ No newline at end of file diff --git a/template/dependency_changed_template.html b/template/dependency_changed_template.html new file mode 100644 index 0000000..67e0ed4 --- /dev/null +++ b/template/dependency_changed_template.html @@ -0,0 +1,6 @@ +
+ {{package_name}} | {{previous_version}} -> {{current_version}} | {{dependency_type}} +
+ {{changelog_diff}} +
+
\ No newline at end of file diff --git a/template/dependency_group_template.html b/template/dependency_group_template.html new file mode 100644 index 0000000..873f6f9 --- /dev/null +++ b/template/dependency_group_template.html @@ -0,0 +1,6 @@ +
+ {{group_name}} +
+ {{changed_dependencies}} +
+
\ No newline at end of file diff --git a/template/no_changed_dependencies_template.html b/template/no_changed_dependencies_template.html new file mode 100644 index 0000000..f0f67ee --- /dev/null +++ b/template/no_changed_dependencies_template.html @@ -0,0 +1,3 @@ +
+No changed dependencies +
\ No newline at end of file diff --git a/test/bubbler_shell_test.dart b/test/bubbler_shell_test.dart new file mode 100644 index 0000000..28e53d9 --- /dev/null +++ b/test/bubbler_shell_test.dart @@ -0,0 +1,17 @@ +import 'package:changelog_bubbler/src/bubbler_shell.dart'; +import 'package:process_run/shell.dart'; +import 'package:test/test.dart'; +import 'package:path/path.dart' as p; + +void main() { + test('runSync executes script in working directory', () { + final shell = BubblerShell.globalConstructor(); + final result = shell.runSync('pwd', workingDir: 'lib'); + expect(result.outText, contains(p.join('changelog_bubbler', 'lib'))); + }); + test('run executes script in working directory', () async { + final shell = BubblerShell.globalConstructor(); + final result = await shell.run('pwd', workingDir: 'lib'); + expect(result.outText, contains(p.join('changelog_bubbler', 'lib'))); + }); +} diff --git a/test/changelog_bubbler_test.dart b/test/changelog_bubbler_test.dart index 3f37d7d..88345cb 100644 --- a/test/changelog_bubbler_test.dart +++ b/test/changelog_bubbler_test.dart @@ -1,6 +1,7 @@ -import 'dart:io'; - +import 'package:changelog_bubbler/src/bubbler_shell.dart'; import 'package:changelog_bubbler/src/changelog_bubbler.dart'; +import 'package:changelog_bubbler/src/global_dependencies.dart'; +import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; import 'package:test_descriptor/test_descriptor.dart' as d; @@ -10,39 +11,61 @@ void main() { setUp(() async { await registerMockGlobalDependencies(); }); - test('validateWorkingDir ensures directory is a git repo', () async { + test('validateWorkingDir throws if not a git repo', () async { final bubbler = ChangelogBubbler(workingDirectory: d.sandbox); - await _prepareTestApp(); - Directory(d.path('.git')).deleteSync(); + await _prepareTestApp(withGit: false); - expect( - () => bubbler.validateWorkingDir(), + await expectLater( + bubbler.validateWorkingDir(), throwsA( isA().having( (e) => e.toString(), 'message', - 'Exception: .git folder found. Program must be run from a git repository', + 'Exception: .git folder not found. Program must be run from a git repository', ), )); }); - test('validateWorkingDir ensures directory has pubspec.yaml', () async { + test('validateWorkingDir does not throw if git folder is found', () async { + final bubbler = ChangelogBubbler(workingDirectory: d.sandbox); + await _prepareTestApp(withGit: true); + + await expectLater(bubbler.validateWorkingDir(), completes); + }); + test('runPubGet executes a pub get', () async { final bubbler = ChangelogBubbler(workingDirectory: d.sandbox); - await _prepareTestApp(); - File(d.path('pubspec.yaml')).deleteSync(); + final shell = getDep(); + + await _prepareTestApp(withGit: false); + await bubbler.runPubGet(); + verify( + () => shell.run('dart pub get', workingDir: any(named: 'workingDir'))); + }); + test('runPubGet throws if pub get fails', () async { + final bubbler = ChangelogBubbler(workingDirectory: d.sandbox); + final shell = getDep(); + + await _prepareTestApp(withGit: false); + when(() => shell.stubbedRun('dart pub get')) + .thenThrow(Exception('mock error')); - expect( - () => bubbler.validateWorkingDir(), + await expectLater( + bubbler.runPubGet(), throwsA( isA().having( (e) => e.toString(), 'message', - 'Exception: pubspec.yaml not found. Program must be run from a dart repository', + 'Exception: `dart pub get` errored out. Program must be run from the root of a dart project. Error: Exception: mock error', ), )); }); } -Future _prepareTestApp() async { - await d.dir('.git').create(); - await d.file('pubspec.yaml').create(); +Future _prepareTestApp({required bool withGit}) async { + if (withGit) { + await d.dir('.git').create(); + } + final shell = getDep(); + final mockResult = MockProcessResult(); + when(() => shell.stubbedRun('dart pub get')) + .thenAnswer((_) async => mockResult); } diff --git a/test/changelog_builder_test.dart b/test/changelog_builder_test.dart new file mode 100644 index 0000000..f5adc82 --- /dev/null +++ b/test/changelog_builder_test.dart @@ -0,0 +1,115 @@ +import 'package:changelog_bubbler/src/bubbler_shell.dart'; +import 'package:changelog_bubbler/src/change_manager.dart'; +import 'package:changelog_bubbler/src/changelog_builder.dart'; +import 'package:changelog_bubbler/src/dependency_parser.dart'; +import 'package:changelog_bubbler/src/dependency_type.dart'; +import 'package:changelog_bubbler/src/global_dependencies.dart'; +import 'package:changelog_bubbler/src/package_wrapper.dart'; +import 'package:changelog_bubbler/src/template_manager.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pub_semver/pub_semver.dart'; +import 'package:pubspec_lock_parse/pubspec_lock_parse.dart'; +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; + +import 'test_helpers.dart'; + +void main() { + setUp(() async { + await registerMockGlobalDependencies(); + await _prepareTestApp(); + }); + test('creates new section for each host', () async { + final parserPrevious = DependencyParser(repoPath: d.sandbox) + ..dependencies = _previousDependencyMap; + final parserCurrent = DependencyParser(repoPath: d.sandbox) + ..dependencies = _currentDependencyMap; + + final diffBuilder = ChangelogBuilder( + changeManager: ChangeManager( + previous: parserPrevious, + current: parserCurrent, + ), + changelogName: 'changelogName', + changelogTemplate: TemplateManager( + '', + templateForTesting: '{{dependency_groups}}', + ), + depGroupTemplate: TemplateManager( + '', + templateForTesting: '{{group_name}}', + ), + depChangedTemplate: TemplateManager('', templateForTesting: ''), + depAddedOrRemovedTemplate: TemplateManager('', templateForTesting: ''), + noChangedDependenciesTemplate: + TemplateManager('', templateForTesting: ''), + ); + + final generatedDiff = await diffBuilder.buildChangelogFromTemplates(); + expect(generatedDiff, contains('hosted_url')); + expect(generatedDiff, contains('git_url')); + expect(generatedDiff, contains('pub_dev_url')); + }); +} + +Future _prepareTestApp() async { + final pubYaml = d.file('pubspec.yaml'); + await pubYaml.create(); + pubYaml.io.writeAsStringSync(MockData.mockPubYamlContents); + + final pubLock = d.file('pubspec.lock'); + await pubLock.create(); + pubLock.io.writeAsStringSync(MockData.mockPubLockContents); + + final shell = getDep(); + final mockResult = ProcessResultExt.mock(outText: MockData.mockPubDepsOutput); + when( + () => shell.stubbedRunSync('dart pub deps --no-dev --style compact'), + ).thenReturn(mockResult); +} + +final _previousDependencyMap = { + 'hosted_dep': PackageWrapper( + 'hosted_dep', + Package( + dependency: 'direct main', + description: HostedPackageDescription(name: 'name', url: 'hosted_url'), + source: PackageSource.hosted, + version: Version.parse('1.0.0'), + ), + DependencyType.directMain, + ), + 'git_dep': PackageWrapper( + 'git_dep', + Package( + dependency: 'direct main', + description: GitPackageDescription( + path: 'path', ref: 'ref', resolvedRef: 'resolvedRef', url: 'git_url'), + source: PackageSource.git, + version: Version.parse('1.0.0'), + ), + DependencyType.directMain, + ), +}; +final _currentDependencyMap = { + 'hosted_dep': PackageWrapper( + 'hosted_dep', + Package( + dependency: 'direct main', + description: HostedPackageDescription(name: 'name', url: 'hosted_url'), + source: PackageSource.hosted, + version: Version.parse('2.0.0'), + ), + DependencyType.directMain, + ), + 'pub_dev_dep': PackageWrapper( + 'pub_dev_dep', + Package( + dependency: 'direct dev', + description: HostedPackageDescription(name: 'name', url: 'pub_dev_url'), + source: PackageSource.hosted, + version: Version.parse('2.0.0'), + ), + DependencyType.directMain, + ), +}; diff --git a/test/dependency_parser_test.dart b/test/dependency_parser_test.dart new file mode 100644 index 0000000..f0e8c3a --- /dev/null +++ b/test/dependency_parser_test.dart @@ -0,0 +1,98 @@ +import 'package:changelog_bubbler/src/bubbler_shell.dart'; +import 'package:changelog_bubbler/src/dependency_parser.dart'; +import 'package:changelog_bubbler/src/global_dependencies.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; + +import 'test_helpers.dart'; + +void main() { + setUp(() async { + await registerMockGlobalDependencies(); + await _prepareTestApp(); + }); + test( + 'includes transitive main dependencies ' + 'when includeTransitive', () async { + final parser = DependencyParser(repoPath: d.sandbox); + + parser.parseDependencies( + includeDev: true, + includeTransitive: true, + ); + + expect(parser.dependencies.keys, contains('async')); + }); + + test( + 'includes direct dev dependencies ' + 'when includeDev', () async { + final parser = DependencyParser(repoPath: d.sandbox); + + parser.parseDependencies( + includeDev: true, + includeTransitive: true, + ); + + expect(parser.dependencies.keys, contains('mocktail')); + }); + test( + 'includes transitive dev dependencies ' + 'when includeDev and includeTransitive', () async { + final parser = DependencyParser(repoPath: d.sandbox); + + parser.parseDependencies( + includeDev: true, + includeTransitive: true, + ); + + expect(parser.dependencies.keys, contains('matcher')); + }); + test( + 'excludes direct dev dependencies ' + 'when not includeDev', () async { + final parser = DependencyParser(repoPath: d.sandbox); + + parser.parseDependencies( + includeDev: false, + includeTransitive: true, + ); + + expect( + parser.dependencies.keys.contains('mocktail'), + isFalse, + ); + }); + test( + 'excludes transitive dev dependencies ' + 'when includeDev and not includeTransitive', () async { + final parser = DependencyParser(repoPath: d.sandbox); + + parser.parseDependencies( + includeDev: true, + includeTransitive: false, + ); + + expect( + parser.dependencies.keys.contains('matcher'), + isFalse, + ); + }); +} + +Future _prepareTestApp() async { + final pubYaml = d.file('pubspec.yaml'); + await pubYaml.create(); + pubYaml.io.writeAsStringSync(MockData.mockPubYamlContents); + + final pubLock = d.file('pubspec.lock'); + await pubLock.create(); + pubLock.io.writeAsStringSync(MockData.mockPubLockContents); + + final shell = getDep(); + final mockResult = ProcessResultExt.mock(outText: MockData.mockPubDepsOutput); + when( + () => shell.stubbedRunSync('dart pub deps --no-dev --style compact'), + ).thenReturn(mockResult); +} diff --git a/test/diff_builder_test.dart b/test/diff_builder_test.dart deleted file mode 100644 index a210b5d..0000000 --- a/test/diff_builder_test.dart +++ /dev/null @@ -1,10 +0,0 @@ -// test added packages -// test removed packages - -import 'package:test/test.dart'; - -void main() { - test('empty test', () { - expect(2 + 2, 4); - }); -} diff --git a/test/global_dependencies_test.dart b/test/global_dependencies_test.dart new file mode 100644 index 0000000..cfc5735 --- /dev/null +++ b/test/global_dependencies_test.dart @@ -0,0 +1,14 @@ +import 'package:changelog_bubbler/src/bubbler_shell.dart'; +import 'package:changelog_bubbler/src/global_dependencies.dart'; +import 'package:changelog_bubbler/src/platform_wrapper.dart'; +import 'package:get_it/get_it.dart'; +import 'package:test/test.dart'; + +void main() { + test('registerGlobalDependencies registers global dependencies', () { + GetIt.I.reset(); + registerGlobalDependencies(); + expect(GetIt.I.isRegistered(), isTrue); + expect(GetIt.I.isRegistered(), isTrue); + }); +} diff --git a/test/package_wrapper_test.dart b/test/package_wrapper_test.dart new file mode 100644 index 0000000..df4c55d --- /dev/null +++ b/test/package_wrapper_test.dart @@ -0,0 +1,162 @@ +import 'package:changelog_bubbler/src/dependency_type.dart'; +import 'package:changelog_bubbler/src/global_dependencies.dart'; +import 'package:changelog_bubbler/src/package_wrapper.dart'; +import 'package:changelog_bubbler/src/platform_wrapper.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:path/path.dart' as p; +import 'package:pub_semver/pub_semver.dart'; +import 'package:pubspec_lock_parse/pubspec_lock_parse.dart'; +import 'package:test/test.dart'; + +import 'test_helpers.dart'; + +// [START] Mocks + +const _mockHash = 'abcd123'; +final _mockVersion = Version.parse('0.0.1'); + +PackageWrapper _mockGitWrapper([Version? version]) { + return PackageWrapper( + 'mockName', + Package( + dependency: 'mockDependency', + description: GitPackageDescription( + path: 'mockPath', + ref: 'mockRef', + resolvedRef: _mockHash, + url: 'mockUrl', + ), + source: PackageSource.git, + version: version ?? _mockVersion, + ), + DependencyType.directMain, + ); +} + +PackageWrapper _mockHostedWrapper({Version? version, String? url}) { + return PackageWrapper( + 'mockName', + Package( + dependency: 'mockDependency', + description: HostedPackageDescription( + url: url ?? 'mockUrl', + name: 'mockName', + ), + source: PackageSource.hosted, + version: version ?? _mockVersion, + ), + DependencyType.directMain, + ); +} + +// [END] Mocks + +void main() { + test( + 'version resolves to ref ' + 'when git package', () { + final wrapper = _mockGitWrapper(); + expect(wrapper.version, _mockHash); + }); + test( + 'version resolves to version ' + 'when hosted package', () { + final wrapper = _mockHostedWrapper(); + expect(wrapper.version, _mockVersion.toString()); + }); + test( + 'accurately compares versions ' + 'when versions are the same', () { + final wrapper1 = _mockHostedWrapper(version: Version.parse('0.0.1')); + final wrapper2 = _mockHostedWrapper(version: Version.parse('0.0.1')); + expect(wrapper1.sameVersion(wrapper2), isTrue); + }); + test( + 'accurately compares versions ' + 'when versions are different', () { + final wrapper1 = _mockHostedWrapper(version: Version.parse('0.0.1')); + final wrapper2 = _mockHostedWrapper(version: Version.parse('0.1.0')); + expect(wrapper1.sameVersion(wrapper2), isFalse); + }); + test( + 'accurately builds pub cache path ' + 'for git package on Windows', () async { + await registerMockGlobalDependencies(); + when(() => getDep().isWindows).thenReturn(true); + + final wrapper = _mockGitWrapper(); + expect( + wrapper.getPubCachePath(), + p.join('%LOCALAPPDATA%\\Pub\\Cache', 'git', 'mockName-$_mockHash'), + ); + }); + test( + 'accurately builds pub cache path ' + 'for git package on Mac', () async { + await registerMockGlobalDependencies(); + final platform = getDep(); + when(() => platform.isWindows).thenReturn(false); + when(() => platform.home).thenReturn('mockHome'); + + final wrapper = _mockGitWrapper(); + expect( + wrapper.getPubCachePath(), + p.join('mockHome/.pub-cache', 'git', 'mockName-$_mockHash'), + ); + }); + test( + 'accurately builds pub cache path ' + 'for hosted package on Windows', () async { + await registerMockGlobalDependencies(); + final platform = getDep(); + when(() => platform.isWindows).thenReturn(true); + + final wrapper = _mockHostedWrapper(); + expect( + wrapper.getPubCachePath(), + p.join( + '%LOCALAPPDATA%\\Pub\\Cache', + 'hosted', + 'mockUrl', + 'mockName-$_mockVersion', + ), + ); + }); + test( + 'accurately builds pub cache path ' + 'for hosted package on Mac', () async { + await registerMockGlobalDependencies(); + final platform = getDep(); + when(() => platform.isWindows).thenReturn(false); + when(() => platform.home).thenReturn('mockHome'); + + final wrapper = _mockHostedWrapper(); + expect( + wrapper.getPubCachePath(), + p.join( + 'mockHome/.pub-cache', + 'hosted', + 'mockUrl', + 'mockName-$_mockVersion', + ), + ); + }); + test( + 'trimmedUrl ' + 'cuts https:// from front', () async { + final wrapper = _mockHostedWrapper(url: 'https://mockUrl'); + expect(wrapper.trimmedUrl, 'mockUrl'); + }); + test( + 'url ' + 'parses git url', () async { + final wrapper = _mockGitWrapper(); + expect(wrapper.url, 'mockUrl'); + }); + test( + 'url ' + 'parses hosted url', () async { + final wrapper = _mockHostedWrapper(); + expect(wrapper.url, 'mockUrl'); + }); +} diff --git a/test/pubspec_lock_parser_test.dart b/test/pubspec_lock_parser_test.dart index 090930f..6302853 100644 --- a/test/pubspec_lock_parser_test.dart +++ b/test/pubspec_lock_parser_test.dart @@ -137,4 +137,4 @@ transitive dependencies: - synchronized 3.1.0 - term_glyph 1.2.1 - yaml 3.1.2 [collection source_span string_scanner] -*/ \ No newline at end of file +*/ diff --git a/test/repository_preparer_test.dart b/test/repository_preparer_test.dart index 8e8a299..cc63269 100644 --- a/test/repository_preparer_test.dart +++ b/test/repository_preparer_test.dart @@ -14,7 +14,8 @@ void main() { test('prepareTempRepo cleans git state of copied repo', () async { final shell = getDep(); - final sut = RepositoryPreparer(repoPath: 'mockDir', passedRef: 'mockPassedRef'); + final sut = + RepositoryPreparer(repoPath: 'mockDir', passedRef: 'mockPassedRef'); await sut.prepareTempRepo(); verify(() => shell.stubbedRun('git clean -dfx', workingDir: 'mockDir')); verify(() => shell.stubbedRun('git add --all', workingDir: 'mockDir')); @@ -23,9 +24,11 @@ void main() { test('prepareTempRepo uses passed ref if not null', () async { final shell = getDep(); - final sut = RepositoryPreparer(repoPath: 'mockDir', passedRef: 'mockPassedRef'); + final sut = + RepositoryPreparer(repoPath: 'mockDir', passedRef: 'mockPassedRef'); await sut.prepareTempRepo(); - verify(() => shell.stubbedRun('git checkout mockPassedRef', workingDir: 'mockDir')); + verify(() => + shell.stubbedRun('git checkout mockPassedRef', workingDir: 'mockDir')); verifyNever(() => shell.stubbedRun('git describe --tags --abbrev=0 HEAD^')); }); test('prepareTempRepo gets previous tag if passed ref is null', () async { @@ -39,14 +42,18 @@ void main() { verify(() => shell.stubbedRun('git describe --tags --abbrev=0 HEAD^')); verify(() => shell.stubbedRun('git checkout mockTag')); }); - test('prepareTempRepo gets previous commit if passed ref is null and previous tag is empty', () async { + test( + 'prepareTempRepo gets previous commit if passed ref is null and previous tag is empty', + () async { final shell = getDep(); final mockTagResult = MockProcessResult(); final mockCommitResult = MockProcessResult(); when(() => mockTagResult.outText).thenReturn(''); - when(() => shell.stubbedRun(any(that: contains('git describe')))).thenAnswer((_) async => mockTagResult); + when(() => shell.stubbedRun(any(that: contains('git describe')))) + .thenAnswer((_) async => mockTagResult); when(() => mockCommitResult.outText).thenReturn('mockCommit'); - when(() => shell.stubbedRun(any(that: contains('git rev-parse')))).thenAnswer((_) async => mockCommitResult); + when(() => shell.stubbedRun(any(that: contains('git rev-parse')))) + .thenAnswer((_) async => mockCommitResult); final sut = RepositoryPreparer(repoPath: 'mockDir'); await sut.prepareTempRepo(); diff --git a/test/test_helpers.dart b/test/test_helpers.dart index 7521485..8ae3a32 100644 --- a/test/test_helpers.dart +++ b/test/test_helpers.dart @@ -1,17 +1,22 @@ import 'dart:io'; import 'package:changelog_bubbler/src/bubbler_shell.dart'; +import 'package:changelog_bubbler/src/platform_wrapper.dart'; import 'package:get_it/get_it.dart'; import 'package:mocktail/mocktail.dart'; +import 'package:process_run/process_run.dart' show ProcessRunProcessResultExt; class MockProcessResult extends Mock implements ProcessResult {} class _MockBubblerShell extends Mock implements BubblerShell {} +class _MockPlatformWrapper extends Mock implements PlatformWrapper {} + Future registerMockGlobalDependencies() async { await GetIt.I.reset(); _stubShell(); + _stubPlatformWrapper(); } void _stubShell() { @@ -21,10 +26,16 @@ void _stubShell() { any(), workingDir: any(named: 'workingDir'), )).thenAnswer((_) async => mockResult); - GetIt.I.registerLazySingleton(() => mockShell); } +void _stubPlatformWrapper() { + final mockPlatformWrapper = _MockPlatformWrapper(); + when(() => mockPlatformWrapper.isWindows).thenReturn(false); + when(() => mockPlatformWrapper.home).thenReturn('mock_home/.pub-cache'); + GetIt.I.registerLazySingleton(() => mockPlatformWrapper); +} + extension TestHelper on BubblerShell { Future stubbedRun( String script, { @@ -34,4 +45,90 @@ extension TestHelper on BubblerShell { script, workingDir: workingDir ?? any(named: 'workingDir'), ); + + ProcessResult stubbedRunSync( + String script, { + String? workingDir, + }) => + runSync( + script, + workingDir: workingDir ?? any(named: 'workingDir'), + ); +} + +extension ProcessResultExt on ProcessResult { + static ProcessResult mock({String? outText}) { + final mockResult = MockProcessResult(); + when(() => mockResult.outText).thenReturn(outText ?? ''); + return mockResult; + } +} + +class MockData { + /// > dart pub deps --no-dev --style compact + static const mockPubDepsOutput = ''' +Dart SDK 2.19.2 +Flutter SDK 3.7.3 +changelog_bubbler 0.1.0 + +dependencies: +- get_it 7.6.0 [async] + +transitive dependencies: +- async 2.11.0 +'''; + + static const mockPubYamlContents = ''' +name: changelog_bubbler +version: 1.0.0 + +dependencies: + get_it: ^7.4.1 + +dev_dependencies: + mocktail: ^0.3.0 + +executables: + changelog_bubbler: changelog_bubbler +'''; + + static const mockPubLockContents = ''' +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: "529de303c739fca98cd7ece5fca500d8ff89649f1bb4b4e94fb20954abcd7468" + url: "https://pub.dev" + source: hosted + version: "7.6.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + mocktail: + dependency: "direct dev" + description: + name: mocktail + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" + source: hosted + version: "0.3.0" +sdks: + dart: ">=2.19.0 <3.0.0" +'''; } diff --git a/tool/validate_version_bump.dart b/tool/validate_version_bump.dart new file mode 100644 index 0000000..cd5cc3b --- /dev/null +++ b/tool/validate_version_bump.dart @@ -0,0 +1,20 @@ +import 'dart:io'; + +import 'package:pub_api_client/pub_api_client.dart'; +import 'package:pubspec_parse/pubspec_parse.dart'; + +Future main(List args) async { + final pubspecStr = File('pubspec.yaml').readAsStringSync(); + final pubspec = Pubspec.parse(pubspecStr); + final packageName = pubspec.name; + final packageVersion = pubspec.version.toString(); + + try { + await PubClient().packageVersionInfo(packageName, packageVersion); + } catch (error) { + print('Success! Version was not found on pub.dev'); + return; + } + throw Exception( + 'Error: Version $packageVersion was found on pub.dev. You must bump the package version for a PR to be accepted.'); +}