Skip to content
Open
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- `docs/config.md`
- `docs/triggers.md`
- `test/README.md`
- Require `analyzer: ^13.0.0`.
- Require `sdk: ^3.11.0`.

## 0.5.2

Expand Down
1 change: 0 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,4 @@ linter:
- sort_constructors_first
- sort_unnamed_constructors_first
- unnecessary_ignore
- use_if_null_to_convert_nulls_to_bools
- use_string_buffers
92 changes: 35 additions & 57 deletions lib/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
}
} else {
final nameArg = args.first;
final paramName = _extractStringLiteral(nameArg);
final paramName = _extractStringLiteral(nameArg as Expression?);
if (paramName != null) {
// Map variable name to actual param name
_variableToParamName[variable.name.lexeme] = paramName;
Expand Down Expand Up @@ -835,11 +835,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
InstanceCreationExpression node,
String fieldName,
) {
final arg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == fieldName)
.map((e) => e.expression)
.firstOrNull;
final arg = node.findNamedArg(fieldName);

if (arg is! SetOrMapLiteral || !arg.isMap) return null;

Expand All @@ -861,21 +857,17 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
Map<String, dynamic>? _extractTaskQueueRetryConfig(
InstanceCreationExpression node,
) {
final retryConfigArg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == 'retryConfig')
.map((e) => e.expression)
.firstOrNull;
final retryConfigArg = node.findNamedArg('retryConfig');

if (retryConfigArg is! InstanceCreationExpression) return null;

final config = <String, dynamic>{};

for (final arg in retryConfigArg.argumentList.arguments) {
if (arg is! NamedExpression) continue;
if (arg is! NamedArgument) continue;

final fieldName = arg.name.label.name;
final value = _extractRetryConfigValue(arg.expression);
final fieldName = arg.name.lexeme;
final value = _extractRetryConfigValue(arg.argumentExpression);
if (value != null) {
config[fieldName] = value;
}
Expand All @@ -888,21 +880,17 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
Map<String, dynamic>? _extractTaskQueueRateLimits(
InstanceCreationExpression node,
) {
final rateLimitsArg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == 'rateLimits')
.map((e) => e.expression)
.firstOrNull;
final rateLimitsArg = node.findNamedArg('rateLimits');

if (rateLimitsArg is! InstanceCreationExpression) return null;

final config = <String, dynamic>{};

for (final arg in rateLimitsArg.argumentList.arguments) {
if (arg is! NamedExpression) continue;
if (arg is! NamedArgument) continue;

final fieldName = arg.name.label.name;
final value = _extractRetryConfigValue(arg.expression);
final fieldName = arg.name.lexeme;
final value = _extractRetryConfigValue(arg.argumentExpression);
if (value != null) {
config[fieldName] = value;
}
Expand All @@ -913,11 +901,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {

/// Extracts timeZone from ScheduleOptions.
String? _extractSchedulerTimeZone(InstanceCreationExpression node) {
final timeZoneArg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == 'timeZone')
.map((e) => e.expression)
.firstOrNull;
final timeZoneArg = node.findNamedArg('timeZone');

if (timeZoneArg is InstanceCreationExpression) {
// TimeZone('America/New_York')
Expand All @@ -931,21 +915,17 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {

/// Extracts RetryConfig from ScheduleOptions.
Map<String, dynamic>? _extractRetryConfig(InstanceCreationExpression node) {
final retryConfigArg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == 'retryConfig')
.map((e) => e.expression)
.firstOrNull;
final retryConfigArg = node.findNamedArg('retryConfig');

if (retryConfigArg is! InstanceCreationExpression) return null;

final config = <String, dynamic>{};

for (final arg in retryConfigArg.argumentList.arguments) {
if (arg is! NamedExpression) continue;
if (arg is! NamedArgument) continue;

final fieldName = arg.name.label.name;
final value = _extractRetryConfigValue(arg.expression);
final fieldName = arg.name.lexeme;
final value = _extractRetryConfigValue(arg.argumentExpression);
if (value != null) {
config[fieldName] = value;
}
Expand All @@ -969,11 +949,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {

/// Extracts a boolean field from an InstanceCreationExpression.
bool? _extractBoolField(InstanceCreationExpression node, String fieldName) {
final arg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == fieldName)
.map((e) => e.expression)
.firstOrNull;
final arg = node.findNamedArg(fieldName);

if (arg is BooleanLiteral) {
return arg.value;
Expand Down Expand Up @@ -1019,7 +995,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
}

/// Common logic for extracting parameter definitions from arguments.
void _extractParamFromArgs(NodeList<Expression> args, String functionName) {
void _extractParamFromArgs(NodeList<Argument> args, String functionName) {
if (args.isEmpty) return;

String? paramName;
Expand Down Expand Up @@ -1053,7 +1029,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
} else {
// Standard parameter definitions: defineXxx('NAME', [ParamOptions])
final nameArg = args.first;
paramName = _extractStringLiteral(nameArg);
paramName = _extractStringLiteral(nameArg as Expression?);

// Second argument is optional ParamOptions (not used for secrets)
if (args.length > 1 && args[1] is InstanceCreationExpression) {
Expand Down Expand Up @@ -1100,11 +1076,7 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {

/// Extracts the defaultValue field.
Object? _extractDefaultValue(InstanceCreationExpression node) {
final defaultValueArg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == 'defaultValue')
.map((e) => e.expression)
.firstOrNull;
final defaultValueArg = node.findNamedArg('defaultValue');

if (defaultValueArg == null) return null;

Expand All @@ -1116,23 +1088,29 @@ class _FirebaseFunctionsVisitor extends RecursiveAstVisitor<void> {
InstanceCreationExpression node,
String fieldName,
) {
final arg = node.argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == fieldName)
.map((e) => e.expression)
.firstOrNull;
final arg = node.findNamedArg(fieldName);

return _extractStringLiteral(arg);
}
}

extension on MethodInvocation {
extension on ArgumentList {
/// Finds a named argument in a method invocation.
Expression? findNamedArg(String name) => argumentList.arguments
.whereType<NamedExpression>()
.where((e) => e.name.label.name == name)
.map((e) => e.expression)
Expression? findNamedArg(String name) => arguments
.whereType<NamedArgument>()
.where((e) => e.name.lexeme == name)
.map((e) => e.argumentExpression)
.firstOrNull;
}

extension on InstanceCreationExpression {
/// Finds a named argument in a method invocation.
Expression? findNamedArg(String name) => argumentList.findNamedArg(name);
}

extension on MethodInvocation {
/// Finds a named argument in a method invocation.
Expression? findNamedArg(String name) => argumentList.findNamedArg(name);

String? extractLiteralForArg(String name) =>
_extractStringLiteral(findNamedArg(name));
Expand Down
20 changes: 10 additions & 10 deletions lib/src/builder/spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ class EndpointSpec {
final result = <String, dynamic>{};

for (final arg in options!.argumentList.arguments) {
if (arg is! NamedExpression) continue;
if (arg is! NamedArgument) continue;

final name = arg.name.label.name;
final expr = arg.expression;
final name = arg.name.lexeme;
final expr = arg.argumentExpression;

// Helper to reduce boilerplate: only adds to map if value exists
void add(String key, dynamic Function(Expression expr) func) {
Expand Down Expand Up @@ -186,7 +186,7 @@ class EndpointSpec {
// Check if it's Memory.expression() - generate CEL from expression
if (expression.constructorName.name?.name == 'expression') {
return _extractCelExpression(
expression.argumentList.arguments.firstOrNull,
expression.argumentList.arguments.firstOrNull as Expression?,
);
}

Expand All @@ -197,7 +197,7 @@ class EndpointSpec {

// Extract literal value: Memory(MemoryOption.mb256) or Memory(.mb256)
final args = expression.argumentList.arguments;
final enumName = _extractEnumValueName(args.firstOrNull);
final enumName = _extractEnumValueName(args.firstOrNull as Expression?);
if (enumName != null) return _memoryOptionToInt(enumName);

return null;
Expand Down Expand Up @@ -256,7 +256,7 @@ class EndpointSpec {

// Extract literal value: Region(SupportedRegion.usCentral1) or Region(.usCentral1)
final args = expression.argumentList.arguments;
final enumName = _extractEnumValueName(args.firstOrNull);
final enumName = _extractEnumValueName(args.firstOrNull as Expression?);
if (enumName != null) {
final regionString = _regionEnumToString(enumName);
return regionString != null ? [regionString] : null;
Expand Down Expand Up @@ -373,7 +373,7 @@ class EndpointSpec {
if (expression is! InstanceCreationExpression) return null;

final args = expression.argumentList.arguments;
final enumName = _extractEnumValueName(args.firstOrNull);
final enumName = _extractEnumValueName(args.firstOrNull as Expression?);
if (enumName != null) {
return switch (enumName) {
'privateRangesOnly' => 'PRIVATE_RANGES_ONLY',
Expand All @@ -390,7 +390,7 @@ class EndpointSpec {
if (expression is! InstanceCreationExpression) return null;

final args = expression.argumentList.arguments;
final enumName = _extractEnumValueName(args.firstOrNull);
final enumName = _extractEnumValueName(args.firstOrNull as Expression?);
if (enumName != null) {
return switch (enumName) {
'allowAll' => 'ALLOW_ALL',
Expand Down Expand Up @@ -506,8 +506,8 @@ class EndpointSpec {
// Extract the two arguments
final args = expression.argumentList.arguments;
if (args.length >= 2) {
final trueValue = _extractLiteralValue(args[0]);
final falseValue = _extractLiteralValue(args[1]);
final trueValue = _extractLiteralValue(args[0] as Expression);
final falseValue = _extractLiteralValue(args[1] as Expression);
if (trueValue != null && falseValue != null) {
return '{{ params.$paramName ? $trueValue : $falseValue }}';
}
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ version: 0.6.0-wip
repository: https://github.com/firebase/firebase-functions-dart

environment:
sdk: ^3.9.0
sdk: ^3.11.0

workspace:
- example/https
Expand All @@ -39,7 +39,7 @@ workspace:
- test/fixtures/dart_reference

dependencies:
analyzer: '>=10.0.1 <13.0.0'
analyzer: ^13.0.0
build: ^4.0.4
dart_jsonwebtoken: ^3.2.0
firebase_admin_sdk: ^0.5.0
Expand Down
Loading