Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for global functions and variables #1610

Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// An interface to describe a Swift entity's compound membership
abstract interface class CompoundMemeber {
abstract final bool isStatic;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import '../shared/referred_type.dart';
import 'declaration.dart';
import 'executable.dart';
import 'parameterizable.dart';
import 'type_parameterizable.dart';

/// Describes a function-like entity.
abstract interface class FunctionDeclaration
implements Declaration, Parameterizable, Executable, TypeParameterizable {
abstract final ReferredType? returnType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import '../shared/referred_type.dart';
import 'declaration.dart';

/// Describes a variable-like entity.
abstract interface class VariableDeclaration implements Declaration {
abstract final bool isConstant;
abstract final ReferredType type;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,14 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import '../../../_core/interfaces/declaration.dart';
import '../../../_core/interfaces/executable.dart';
import '../../../_core/interfaces/function_declaration.dart';
import '../../../_core/interfaces/objc_annotatable.dart';
import '../../../_core/interfaces/parameterizable.dart';
import '../../../_core/interfaces/type_parameterizable.dart';
import '../../../_core/shared/parameter.dart';
import '../../../_core/shared/referred_type.dart';

/// Describes a method declaration for a Swift compound entity
/// (e.g, class, structs)
class MethodDeclaration
implements
Declaration,
TypeParameterizable,
Executable,
Parameterizable,
ObjCAnnotatable {
class MethodDeclaration implements FunctionDeclaration, ObjCAnnotatable {
@override
String id;

Expand All @@ -37,6 +28,7 @@ class MethodDeclaration
@override
List<String> statements;

@override
ReferredType? returnType;

bool isStatic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import '../../../_core/interfaces/declaration.dart';
import '../../../_core/interfaces/executable.dart';
import '../../../_core/interfaces/objc_annotatable.dart';
import '../../../_core/interfaces/variable_declaration.dart';
import '../../../_core/shared/referred_type.dart';

/// Describes a property declaration for a Swift compound entity
/// (e.g, class, structs)
class PropertyDeclaration implements Declaration, ObjCAnnotatable {
class PropertyDeclaration implements VariableDeclaration, ObjCAnnotatable {
@override
String id;

Expand All @@ -19,25 +19,30 @@ class PropertyDeclaration implements Declaration, ObjCAnnotatable {
@override
bool hasObjCAnnotation;

@override
ReferredType type;

@override
bool isConstant;

bool hasSetter;

PropertyStatements? getter;
PropertyStatements? setter;

ReferredType type;

bool isStatic;

PropertyDeclaration({
required this.id,
required this.name,
required this.type,
this.hasSetter = false,
this.isConstant = false,
this.hasObjCAnnotation = false,
this.getter,
this.setter,
this.isStatic = false,
});
}) : assert(!isConstant || !hasSetter);
}

class PropertyStatements implements Executable {
Expand Down
29 changes: 17 additions & 12 deletions pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,25 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import '../../_core/interfaces/declaration.dart';
import '../../_core/interfaces/parameterizable.dart';
import '../../_core/interfaces/type_parameterizable.dart';
import '../../_core/interfaces/function_declaration.dart';
import '../../_core/interfaces/variable_declaration.dart';
import '../../_core/shared/parameter.dart';
import '../../_core/shared/referred_type.dart';

/// A container for globally defined values (i.e variables & constants)
/// and functions.
class Globals {
List<GlobalFunctionDeclaration> functions;
List<GlobalValueDeclaration> values;
List<GlobalVariableDeclaration> variables;

Globals({
required this.functions,
required this.values,
required this.variables,
});
}

/// Describes a globally defined function.
class GlobalFunctionDeclaration
implements Declaration, Parameterizable, TypeParameterizable {
class GlobalFunctionDeclaration implements FunctionDeclaration {
@override
String id;

Expand All @@ -35,30 +33,37 @@ class GlobalFunctionDeclaration
@override
List<GenericType> typeParams;

ReferredType returnType;
@override
ReferredType? returnType;

@override
List<String> statements;

GlobalFunctionDeclaration({
required this.id,
required this.name,
required this.params,
required this.typeParams,
required this.returnType,
this.typeParams = const [],
this.statements = const [],
});
}

/// Describes a globally defined values (i.e variable/constant).
class GlobalValueDeclaration implements Declaration {
class GlobalVariableDeclaration implements VariableDeclaration {
@override
String id;

@override
String name;

DeclaredType type;
@override
ReferredType type;

@override
bool isConstant;

GlobalValueDeclaration({
GlobalVariableDeclaration({
required this.id,
required this.name,
required this.type,
Expand Down
4 changes: 2 additions & 2 deletions pkgs/swift2objc/lib/src/parser/_core/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extension TopLevelOnly<T extends Declaration> on List<T> {
(declaration) =>
declaration is CompoundDeclaration ||
declaration is EnumDeclaration ||
declaration is GlobalValueDeclaration ||
declaration is GlobalVariableDeclaration ||
declaration is GlobalFunctionDeclaration,
).toList();
}
Expand All @@ -55,7 +55,7 @@ String parseSymbolName(Json symbolJson) {
.get();
}

bool symbolHasObjcAnnotation(Json symbolJson) {
bool parseSymbolHasObjcAnnotation(Json symbolJson) {
return symbolJson['declarationFragments'].any(
(json) =>
json['kind'].exists &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ InitializerDeclaration parseInitializerDeclaration(
return InitializerDeclaration(
id: parseSymbolId(initializerSymbolJson),
params: parseInitializerParams(initializerSymbolJson, symbolgraph),
hasObjCAnnotation: symbolHasObjcAnnotation(initializerSymbolJson),
hasObjCAnnotation: parseSymbolHasObjcAnnotation(initializerSymbolJson),
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '../../../ast/_core/interfaces/declaration.dart';
import '../../../ast/_core/shared/referred_type.dart';
import '../../../ast/declarations/compounds/members/property_declaration.dart';
import '../../../ast/declarations/globals/globals.dart';
import '../../_core/json.dart';
import '../../_core/parsed_symbolgraph.dart';
import '../../_core/utils.dart';
Expand All @@ -11,17 +12,32 @@ PropertyDeclaration parsePropertyDeclaration(
ParsedSymbolgraph symbolgraph, {
bool isStatic = false,
}) {
final isConstant = _parseVariableIsConstant(propertySymbolJson);
return PropertyDeclaration(
id: parseSymbolId(propertySymbolJson),
name: parseSymbolName(propertySymbolJson),
type: _parsePropertyType(propertySymbolJson, symbolgraph),
hasObjCAnnotation: symbolHasObjcAnnotation(propertySymbolJson),
hasSetter: _propertyHasSetter(propertySymbolJson),
type: _parseVariableType(propertySymbolJson, symbolgraph),
hasObjCAnnotation: parseSymbolHasObjcAnnotation(propertySymbolJson),
isConstant: isConstant,
hasSetter: isConstant ? false : _parsePropertyHasSetter(propertySymbolJson),
isStatic: isStatic,
);
}

ReferredType _parsePropertyType(
GlobalVariableDeclaration parseGlobalVariableDeclaration(
Json variableSymbolJson,
ParsedSymbolgraph symbolgraph, {
bool isStatic = false,
}) {
return GlobalVariableDeclaration(
id: parseSymbolId(variableSymbolJson),
name: parseSymbolName(variableSymbolJson),
type: _parseVariableType(variableSymbolJson, symbolgraph),
isConstant: _parseVariableIsConstant(variableSymbolJson),
);
}

ReferredType _parseVariableType(
Json propertySymbolJson,
ParsedSymbolgraph symbolgraph,
) {
Expand All @@ -47,8 +63,8 @@ ReferredType _parsePropertyType(
return typeDeclaration.asDeclaredType;
}

bool _propertyHasSetter(Json propertySymbolJson) {
final fragmentsJson = propertySymbolJson['declarationFragments'];
bool _parseVariableIsConstant(Json variableSymbolJson) {
final fragmentsJson = variableSymbolJson['declarationFragments'];

final declarationKeywordJson = fragmentsJson.firstWhere(
(json) {
Expand All @@ -67,25 +83,38 @@ bool _propertyHasSetter(Json propertySymbolJson) {

final declarationKeyword = declarationKeywordJson['spelling'].get<String>();

if (declarationKeyword == 'var') {
final hasExplicitSetter = fragmentsJson.any(
(json) => json['spelling'].get<String>() == 'set',
);
return declarationKeyword == 'let';
}

final hasExplicitGetter = fragmentsJson.any(
(json) => json['spelling'].get<String>() == 'get',
);
bool _parsePropertyHasSetter(Json propertySymbolJson) {
final fragmentsJson = propertySymbolJson['declarationFragments'];

if (hasExplicitGetter) {
if (hasExplicitSetter) {
return true;
} else {
return false;
}
}
final hasExplicitSetter = fragmentsJson.any(
(json) => json['spelling'].get<String>() == 'set',
);

return true;
}
final hasExplicitGetter = fragmentsJson.any(
(json) => json['spelling'].get<String>() == 'get',
);

return false;
if (hasExplicitGetter) {
if (hasExplicitSetter) {
// has explicit getter and has explicit setter
return true;
} else {
// has explicit getter and no explicit setter
return false;
}
} else {
if (hasExplicitSetter) {
// has no explicit getter and but has explicit setter
throw Exception(
'Invalid property at ${propertySymbolJson.path}. '
'Properties can not have a setter without a getter',
);
} else {
// has no explicit getter and no explicit setter
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@ import '../../../ast/_core/interfaces/declaration.dart';
import '../../../ast/_core/shared/parameter.dart';
import '../../../ast/_core/shared/referred_type.dart';
import '../../../ast/declarations/compounds/members/method_declaration.dart';
import '../../../ast/declarations/globals/globals.dart';
import '../../_core/json.dart';
import '../../_core/parsed_symbolgraph.dart';
import '../../_core/utils.dart';
import '../parse_declarations.dart';

GlobalFunctionDeclaration parseGlobalFunctionDeclaration(
Json globalFunctionSymbolJson,
ParsedSymbolgraph symbolgraph,
) {
return GlobalFunctionDeclaration(
id: parseSymbolId(globalFunctionSymbolJson),
name: parseSymbolName(globalFunctionSymbolJson),
returnType: _parseFunctionReturnType(globalFunctionSymbolJson, symbolgraph),
params: _parseFunctionParams(globalFunctionSymbolJson, symbolgraph),
);
}

MethodDeclaration parseMethodDeclaration(
Json methodSymbolJson,
ParsedSymbolgraph symbolgraph, {
Expand All @@ -19,14 +32,14 @@ MethodDeclaration parseMethodDeclaration(
return MethodDeclaration(
id: parseSymbolId(methodSymbolJson),
name: parseSymbolName(methodSymbolJson),
returnType: _parseMethodReturnType(methodSymbolJson, symbolgraph),
params: _parseMethodParams(methodSymbolJson, symbolgraph),
hasObjCAnnotation: symbolHasObjcAnnotation(methodSymbolJson),
returnType: _parseFunctionReturnType(methodSymbolJson, symbolgraph),
params: _parseFunctionParams(methodSymbolJson, symbolgraph),
hasObjCAnnotation: parseSymbolHasObjcAnnotation(methodSymbolJson),
isStatic: isStatic,
);
}

ReferredType? _parseMethodReturnType(
ReferredType? _parseFunctionReturnType(
Json methodSymbolJson,
ParsedSymbolgraph symbolgraph,
) {
Expand Down Expand Up @@ -56,7 +69,7 @@ ReferredType? _parseMethodReturnType(
return returnTypeDeclaration.asDeclaredType;
}

List<Parameter> _parseMethodParams(
List<Parameter> _parseFunctionParams(
Json methodSymbolJson,
ParsedSymbolgraph symbolgraph,
) {
Expand Down
Loading