-
Notifications
You must be signed in to change notification settings - Fork 81
[swift2objc] Filtering Support #1730
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
Changes from 4 commits
0c6ae4f
6b42b1c
d9a926d
2af7024
34d05ed
93c7879
dbe4ba4
38bbbbc
19e1504
4a7de6a
94926ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
import '../../ast/_core/interfaces/declaration.dart'; | ||
import '../../ast/_core/interfaces/enum_declaration.dart'; | ||
import '../../ast/_core/interfaces/function_declaration.dart'; | ||
import '../../ast/_core/interfaces/variable_declaration.dart'; | ||
import '../../ast/_core/shared/parameter.dart'; | ||
import '../../ast/_core/shared/referred_type.dart'; | ||
import '../../ast/declarations/compounds/class_declaration.dart'; | ||
import '../../ast/declarations/compounds/members/initializer_declaration.dart'; | ||
import '../../ast/declarations/compounds/protocol_declaration.dart'; | ||
import '../../ast/declarations/compounds/struct_declaration.dart'; | ||
|
||
/// Gets the type name from a string type by removing other characters like | ||
Set<String> _getTypeNames(String type) { | ||
// Remove optional markers (?) and square brackets ([]) | ||
type = type.replaceAll(RegExp(r'\?|!|[\[\]]'), ''); | ||
|
||
// Remove annotations (words starting with @) | ||
type = type.replaceAll(RegExp(r'@\w+'), ''); | ||
|
||
// Extract unique type names using regex | ||
final matches = RegExp(r'\b\w+\b').allMatches(type); | ||
|
||
// Return unique type names as a set | ||
return matches.map((match) => match.group(0)!).toSet(); | ||
} | ||
|
||
// TODO: Type restrictions have not yet been implemented in system | ||
|
||
class DependencyVisitor { | ||
Set<String> visitDeclaration(Declaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// switch between declarations | ||
if (decl is ClassDeclaration) | ||
visitClass(decl, cont); | ||
else if (decl is ProtocolDeclaration) | ||
visitProtocol(decl, cont); | ||
else if (decl is StructDeclaration) | ||
visitStruct(decl, cont); | ||
else if (decl is FunctionDeclaration) | ||
visitFunction(decl, cont); | ||
else if (decl is VariableDeclaration) | ||
visitVariable(decl, cont); | ||
else if (decl is EnumDeclaration) visitEnum(decl, cont); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitEnum(EnumDeclaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// TODO: what of raw values of enums? | ||
|
||
// visit nested declarations | ||
decl.nestedDeclarations.forEach((n) => visitDeclaration(n, cont)); | ||
|
||
// visit protocols | ||
decl.conformedProtocols.forEach((p) => visitProtocol(p.declaration, cont)); | ||
|
||
// ensure generic types do not enter | ||
cont.removeWhere((t) => decl.typeParams.map((type) => type.name).contains(t)); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitStruct(StructDeclaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// visit variables | ||
decl.properties.forEach((d) => visitVariable(d, cont)); | ||
|
||
// visit methods | ||
decl.methods.forEach((m) => visitFunction(m, cont)); | ||
|
||
// visit initializers | ||
decl.initializers.forEach((i) => visitInitializer(i, cont)); | ||
|
||
// visit nested declarations | ||
decl.nestedDeclarations.forEach((n) => visitDeclaration(n, cont)); | ||
|
||
// visit protocols | ||
decl.conformedProtocols.forEach((p) => visitProtocol(p.declaration, cont)); | ||
|
||
// ensure generic types do not enter | ||
cont.removeWhere((t) => decl.typeParams.map((type) => type.name).contains(t)); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitClass(ClassDeclaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// visit variables | ||
decl.properties.forEach((d) => visitVariable(d, cont)); | ||
|
||
// visit methods | ||
decl.methods.forEach((m) => visitFunction(m, cont)); | ||
|
||
// visit initializers | ||
decl.initializers.forEach((i) => visitInitializer(i, cont)); | ||
|
||
// visit super if any | ||
if (decl.superClass != null) | ||
visitDeclaration(decl.superClass!.declaration, cont); | ||
|
||
// visit nested declarations | ||
decl.nestedDeclarations.forEach((n) => visitDeclaration(n, cont)); | ||
|
||
// visit protocols | ||
decl.conformedProtocols.forEach((p) => visitProtocol(p.declaration, cont)); | ||
|
||
// ensure generic types do not enter | ||
cont.removeWhere((t) => decl.typeParams.map((type) => type.name).contains(t)); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitProtocol(ProtocolDeclaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// visit variables | ||
decl.properties.forEach((d) => visitVariable(d, cont)); | ||
|
||
// visit methods | ||
decl.methods.forEach((m) => visitFunction(m, cont)); | ||
|
||
// visit initializers | ||
decl.initializers.forEach((i) => visitInitializer(i, cont)); | ||
|
||
// visit nested declarations | ||
decl.nestedDeclarations.forEach((n) => visitDeclaration(n, cont)); | ||
|
||
// visit protocols | ||
decl.conformedProtocols.forEach((p) => visitProtocol(p.declaration, cont)); | ||
|
||
// ensure generic types do not enter | ||
cont.removeWhere((t) => decl.typeParams.map((type) => type.name).contains(t)); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitInitializer(InitializerDeclaration decl, | ||
[Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// similar to `visitMethod`, except no return type | ||
decl.params.forEach((p) => visitParameter(p, cont)); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitFunction(FunctionDeclaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// visit parameters | ||
decl.params.forEach((p) => visitParameter(p, cont)); | ||
|
||
// ensure generic types do not enter | ||
cont.removeWhere((t) => decl.typeParams.map((type) => type.name).contains(t)); | ||
|
||
// visit return type | ||
visitType(decl.returnType, cont); | ||
|
||
// TODO: what of type restrictions (`... where T.Element: CustomStringConvertible`) | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitParameter(Parameter decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// just visit type of parameter | ||
visitType(decl.type, cont); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitVariable(VariableDeclaration decl, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// just return property type | ||
visitType(decl.type, cont); | ||
|
||
return cont; | ||
} | ||
|
||
Set<String> visitType(ReferredType type, [Set<String>? context]) { | ||
final cont = context ??= {}; | ||
|
||
// we need to confirm the types located | ||
// at the moment, we can perform simple regex to clean up text characters | ||
|
||
// since we are making such visitations on normal declarations in a file, | ||
// we do not need to filter out primitives at the moment | ||
cont.addAll(_getTypeNames(type.swiftType)); | ||
|
||
|
||
return cont; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,22 +8,45 @@ import '../ast/_core/interfaces/nestable_declaration.dart'; | |
import '../ast/declarations/compounds/class_declaration.dart'; | ||
import '../ast/declarations/compounds/struct_declaration.dart'; | ||
import '../ast/declarations/globals/globals.dart'; | ||
import '_core/dependencies.dart'; | ||
import '_core/unique_namer.dart'; | ||
import 'transformers/transform_compound.dart'; | ||
import 'transformers/transform_globals.dart'; | ||
|
||
typedef TransformationMap = Map<Declaration, Declaration>; | ||
|
||
/// Transforms the given declarations into the desired ObjC wrapped declarations | ||
List<Declaration> transform(List<Declaration> declarations, { | ||
bool Function(Declaration)? filter | ||
}) { | ||
final TransformationMap transformationMap; | ||
final _filter = filter ?? (declaration) => true; | ||
Set<Declaration> generateDependencies(Iterable<Declaration> decls, {Iterable<Declaration>? allDecls}) { | ||
final dependencies = <Declaration>{}; | ||
final dependencyVisitor = DependencyVisitor(); | ||
|
||
var _d = decls; | ||
|
||
while (true) { | ||
final deps = _d.fold<Set<String>>( | ||
nikeokoronkwo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
{}, | ||
(previous, element) => | ||
previous.union(dependencyVisitor.visitDeclaration(element))); | ||
final depDecls = | ||
(allDecls ?? decls).where((d) => deps.contains(d.name)); | ||
|
||
if (depDecls.isEmpty || (dependencies.union(depDecls.toSet()).length) == dependencies.length) { | ||
break; | ||
} else { | ||
dependencies.addAll(depDecls); | ||
_d = depDecls; | ||
} | ||
} | ||
|
||
return dependencies; | ||
} | ||
|
||
final _declarations = declarations.where((d) => _filter(d)); | ||
/// Transforms the given declarations into the desired ObjC wrapped declarations | ||
List<Declaration> transform(List<Declaration> declarations, | ||
{bool Function(Declaration)? filter}) { | ||
nikeokoronkwo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
final transformationMap = <Declaration, Declaration>{}; | ||
|
||
transformationMap = {}; | ||
final _declarations = | ||
declarations.where(filter ?? (declaration) => true).toSet(); | ||
_declarations.addAll(generateDependencies(_declarations, allDecls: declarations)); | ||
|
||
final globalNamer = UniqueNamer( | ||
_declarations.map((declaration) => declaration.name), | ||
|
Uh oh!
There was an error while loading. Please reload this page.