Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ jobs:
if: startsWith(matrix.os, 'windows')
run: echo "%LOCALAPPDATA%\Pub\Cache\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Get dependencies
run: |
dart pub global activate melos
melos bootstrap
- name: Prepare workspace
uses: bluefireteam/melos-action@v3

- name: Generate test data and see if changes
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: flutter-actions/setup-flutter@v4.0
- name: Install dependencies
run: dart pub get
- name: Prepare Melos workspace
- name: Prepare workspace
uses: bluefireteam/melos-action@v3
- name: Publish
run: melos run publish:force --no-select
run: melos publish:force --no-select
6 changes: 2 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ jobs:
- name: Set environment
run: echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH

- name: Get dependencies
run: |
dart pub global activate melos
melos bootstrap
- name: Prepare workspace
uses: bluefireteam/melos-action@v3

- name: Running build
run: |
Expand Down
14 changes: 8 additions & 6 deletions melos.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: FlutterGen

packages:
- packages/**
- integrations/**
- examples/**
- packages/command
- packages/core
- packages/runner
- examples/example
- examples/example_resources

ide:
intellij:
Expand Down Expand Up @@ -41,7 +43,7 @@ scripts:
description: flutter build apk

gen:build_runner:
exec: dart run build_runner build --delete-conflicting-outputs
exec: dart run build_runner build -d
packageFilters:
ignore:
- example
Expand All @@ -58,14 +60,14 @@ scripts:
description: dart ../../packages/command/bin/flutter_gen_command.dart

gen:examples:build_runner:
run: flutter pub run build_runner build --delete-conflicting-outputs
run: dart run build_runner build -d
exec:
concurrency: 1
packageFilters:
scope:
- example
- example_resources
description: flutter pub run build_runner build --delete-conflicting-outputs
description: dart run build_runner build --delete-conflicting-outputs

gen:actual_data:
run: dart packages/core/scripts/generate_facts.dart
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"private": true,
"author": "wasabeef",
"scripts": {
"format": "prettier --config prettier.config.js --write '**/*.+(md|yml|yaml|json)'",
"format": "prettier --config prettier.config.js --write \"**/*.+(md|yml|yaml|json)\"",
"prepare": "husky install"
},
"lint-staged": {
Expand All @@ -21,5 +21,5 @@
"prettier": "^3.0.3",
"prettier-plugin-packagejson": "^2.4.5"
},
"packageManager": "pnpm@10.22.0"
"packageManager": "pnpm@10.30.3"
}
61 changes: 36 additions & 25 deletions packages/core/lib/generators/integrations/rive_integration.dart
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
import 'package:flutter_gen_core/generators/integrations/integration.dart';
import 'package:pub_semver/pub_semver.dart' show Version, VersionConstraint;

typedef RiveIntegrationLatest = RiveIntegration0140;
import 'package:pub_semver/pub_semver.dart'
show Version, VersionConstraint, VersionRange;

/// Create Rive integration based on the resolved version.
abstract final class RiveIntegration extends Integration {
sealed class RiveIntegration extends Integration {
factory RiveIntegration(
String packageName, {
Version? resolvedVersion,
VersionConstraint? resolvedVersionConstraint,
}) {
// Resolve integration by version.
RiveIntegration? integration = switch (resolvedVersion) {
final v? when v < Version(0, 14, 0) =>
final v? when v < RiveIntegration0140.minimumSupportVersion =>
RiveIntegrationClassic(packageName),
Version() => RiveIntegrationLatest(packageName),
Version() => RiveIntegration0140(packageName),
null => null,
};

// Resolve integration by version constraint.
integration ??= switch (resolvedVersionConstraint) {
final c? when c.allows(Version(0, 14, 0)) =>
RiveIntegrationLatest(packageName),
final VersionRange c => switch (c.max) {
final max? when max == RiveIntegration0140.minimumSupportVersion =>
c.includeMax
? RiveIntegration0140(packageName)
: RiveIntegrationClassic(packageName),
final max? when max > RiveIntegration0140.minimumSupportVersion =>
RiveIntegration0140(packageName),
_ => RiveIntegrationClassic(packageName),
},
VersionConstraint() => RiveIntegrationClassic(packageName),
null => null,
};

// Use the latest integration as the fallback.
integration ??= RiveIntegrationLatest(packageName);
integration ??= RiveIntegration0140(packageName);

return integration;
}

RiveIntegration._(String packageName) : super(packageName);
}

/// Rive integration for versions before 0.14.0.
final class RiveIntegrationClassic extends RiveIntegration {
RiveIntegrationClassic(String packageName) : super._(packageName);
String get _classDefinition;

@override
String get classOutput => _classDefinition;

String? get packageExpression => isPackage ? 'packages/$packageName/' : null;

Expand All @@ -48,8 +54,20 @@ final class RiveIntegrationClassic extends RiveIntegration {
];

@override
String get classOutput => _classDefinition;
String get className => 'RiveGenImage';

@override
bool isSupport(AssetType asset) => asset.extension == '.riv';

@override
bool get isConstConstructor => true;
}

/// Rive integration for versions before 0.14.0.
final class RiveIntegrationClassic extends RiveIntegration {
RiveIntegrationClassic(String packageName) : super._(packageName);

@override
String get _classDefinition => '''class RiveGenImage {
const RiveGenImage(
this._assetName, {
Expand Down Expand Up @@ -92,20 +110,13 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''}

String get keyName => ${isPackage ? '\'$packageExpression\$_assetName\'' : '_assetName'};
}''';

@override
String get className => 'RiveGenImage';

@override
bool isSupport(AssetType asset) => asset.extension == '.riv';

@override
bool get isConstConstructor => true;
}

/// Rive integration for versions equal to or above 0.14.0.
final class RiveIntegration0140 extends RiveIntegrationClassic {
RiveIntegration0140(String packageName) : super(packageName);
final class RiveIntegration0140 extends RiveIntegration {
RiveIntegration0140(String packageName) : super._(packageName);

static final minimumSupportVersion = Version(0, 14, 0, pre: '0');

@override
String get _classDefinition => '''class RiveGenImage {
Expand Down
8 changes: 6 additions & 2 deletions packages/core/lib/settings/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:flutter_gen_core/utils/error.dart';
import 'package:flutter_gen_core/utils/log.dart';
import 'package:flutter_gen_core/utils/map.dart';
import 'package:flutter_gen_core/version.gen.dart';
import 'package:json_annotation/json_annotation.dart'
show CheckedFromJsonException;
import 'package:path/path.dart';
import 'package:pub_semver/pub_semver.dart' show VersionConstraint, Version;
import 'package:yaml/yaml.dart';
Expand Down Expand Up @@ -105,7 +107,7 @@ Config loadPubspecConfig(File pubspecFile, {File? buildFile}) {
final pubspec = Pubspec.fromJson(mergedMap);

final pubspecLockFile = File(
normalize(join(basename(pubspecFile.parent.path), 'pubspec.lock')),
normalize(join(pubspecFile.parent.path, 'pubspec.lock')),
);
final pubspecLockContent = switch (pubspecLockFile.existsSync()) {
true => pubspecLockFile.readAsStringSync(),
Expand All @@ -130,7 +132,7 @@ Config loadPubspecConfig(File pubspecFile, {File? buildFile}) {
}

final analysisOptionsFile = File(
normalize(join(basename(pubspecFile.parent.path), 'analysis_options.yaml')),
normalize(join(pubspecFile.parent.path, 'analysis_options.yaml')),
);
final analysisOptionsContent = switch (analysisOptionsFile.existsSync()) {
true => analysisOptionsFile.readAsStringSync(),
Expand Down Expand Up @@ -165,6 +167,8 @@ Config? loadPubspecConfigOrNull(File pubspecFile, {File? buildFile}) {
log.severe('File system error when reading files.', e, s);
} on InvalidSettingsException catch (e, s) {
log.severe('Invalid settings in files.', e, s);
} on CheckedFromJsonException catch (e, s) {
log.severe('Invalid settings in files.', e, s);
}
return null;
}
5 changes: 2 additions & 3 deletions packages/core/scripts/generate_facts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ late final Directory dir;

void main() async {
dir = File.fromUri(Platform.script).parent.parent.directory('test_resources');
final configFiles = dir.listSync().whereType<File>().where(
(e) => e.extension == '.yaml',
);
final configFiles =
dir.listSync().whereType<File>().where((e) => e.extension == '.yaml');
for (final file in configFiles) {
final File pubspecFile;
final File? buildFile;
Expand Down
100 changes: 95 additions & 5 deletions packages/core/test/assets_gen_integrations_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,20 @@ void main() {
resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'),
);
expect(fallbackIntegration, isA<RiveIntegration0140>());
expect(fallbackIntegration.classOutput.contains('riveFileLoader({'), isTrue);
expect(
fallbackIntegration.classOutput.contains('riveFileLoader({'),
isTrue,
);
});

test('RiveIntegration fallback behavior', () {
// Test with no version information (should return RiveIntegration0140 as fallback)
final fallbackIntegration = RiveIntegration('');
expect(fallbackIntegration, isA<RiveIntegration0140>());
expect(fallbackIntegration.classOutput.contains('riveFileLoader({'), isTrue);
expect(
fallbackIntegration.classOutput.contains('riveFileLoader({'),
isTrue,
);
});

test('RiveIntegrationClassic classOutput structure', () {
Expand Down Expand Up @@ -359,7 +365,7 @@ void main() {
isTrue,
);
expect(
output.contains("'packages/test_package/\$_assetName'"),
output.contains(r"'packages/test_package/$_assetName'"),
isTrue,
);
});
Expand All @@ -376,7 +382,10 @@ void main() {
expect(output.contains('_rive.FileLoader riveFileLoader({'), isTrue);
expect(output.contains('_rive.FileLoader.fromAsset'), isTrue);
expect(output.contains('_rive.Factory? factory,'), isTrue);
expect(output.contains('riveFactory: factory ?? _rive.Factory.rive'), isTrue);
expect(
output.contains('riveFactory: factory ?? _rive.Factory.rive'),
isTrue,
);
expect(output.contains('String get path =>'), isTrue);
expect(output.contains('String get keyName =>'), isTrue);

Expand All @@ -398,7 +407,7 @@ void main() {
isTrue,
);
expect(
output.contains("'packages/test_package/\$_assetName'"),
output.contains(r"'packages/test_package/$_assetName'"),
isTrue,
);
});
Expand Down Expand Up @@ -459,5 +468,86 @@ void main() {
isTrue,
);
});

test('Integration version resolution in AssetsGenConfig', () {
// Test that version resolution is properly integrated into assets generation
// This validates the full flow from config loading to integration creation.
// Create a RiveIntegration with both resolved version and constraint
// When resolvedVersion is 0.13.0 (< 0.14.0), it should use Classic
// even if resolvedVersionConstraint would allow 0.14.0.
final integrationWithBoth = RiveIntegration(
'',
resolvedVersion: Version(0, 13, 0),
resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'),
);
// resolvedVersion takes priority: 0.13.0 < 0.14.0 => Classic
expect(integrationWithBoth, isA<RiveIntegrationClassic>());

// Create a RiveIntegration with only resolvedVersion
final integrationVersionOnly = RiveIntegration(
'',
resolvedVersion: Version(0, 14, 0),
);
expect(integrationVersionOnly, isA<RiveIntegration0140>());

// Create a RiveIntegration with only resolvedVersionConstraint
final integrationConstraintOnly = RiveIntegration(
'',
resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'),
);
expect(integrationConstraintOnly, isA<RiveIntegration0140>());
});

test('Version resolution with various constraint formats', () {
// Test with ^0.13.x constraint (should use Classic)
final caretOld = RiveIntegration(
'',
resolvedVersionConstraint: VersionConstraint.parse('^0.13.5'),
);
expect(caretOld, isA<RiveIntegrationClassic>());

// Test with ^0.14.x constraint (should use 0140)
final caretNew = RiveIntegration(
'',
resolvedVersionConstraint: VersionConstraint.parse('^0.14.1'),
);
expect(caretNew, isA<RiveIntegration0140>());

// Test with >= constraint that includes 0.14.0
final rangeIncludesNew = RiveIntegration(
'',
resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <1.0.0'),
);
expect(rangeIncludesNew, isA<RiveIntegration0140>());

// Test with >= constraint that includes the minimum pre-release.
final rangeIncludesPre = RiveIntegration(
'',
resolvedVersionConstraint:
VersionConstraint.parse('>=0.13.0 <=0.14.0-0'),
);
expect(rangeIncludesPre, isA<RiveIntegration0140>());

// Test with >= constraint that excludes 0.14.0
final rangeExcludesNew = RiveIntegration(
'',
resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <0.14.0'),
);
expect(rangeExcludesNew, isA<RiveIntegrationClassic>());

// Test with exact version < 0.14.0
final exactOld = RiveIntegration(
'',
resolvedVersion: Version(0, 13, 99),
);
expect(exactOld, isA<RiveIntegrationClassic>());

// Test with exact version >= 0.14.0
final exactNew = RiveIntegration(
'',
resolvedVersion: Version(0, 14, 0),
);
expect(exactNew, isA<RiveIntegration0140>());
});
});
}
Loading