-
Notifications
You must be signed in to change notification settings - Fork 34
Add Variable Declaration Support #382
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 all commits
ee45924
91b9220
1d36928
98be9e9
aa297b0
74e738e
e761508
ce859e6
770a513
f41deb6
71db9d8
e9bc7ab
9c3e48a
33b2608
03dd5ba
0512cde
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,169 @@ | ||
// Copyright (c) 2025, 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 'package:code_builder/code_builder.dart'; | ||
|
||
import 'interop_gen/generate.dart'; | ||
import 'interop_gen/namer.dart'; | ||
|
||
sealed class Node { | ||
abstract final String? name; | ||
abstract final ID id; | ||
final String? dartName; | ||
|
||
Node() : dartName = null; | ||
} | ||
|
||
abstract class Declaration extends Node { | ||
nikeokoronkwo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@override | ||
abstract final String name; | ||
|
||
Spec emit(); | ||
} | ||
|
||
abstract class NamedDeclaration extends Declaration { | ||
ReferredType asReferredType([List<Type>? typeArgs]) => | ||
ReferredType(name: name, declaration: this, typeParams: typeArgs ?? []); | ||
} | ||
|
||
abstract interface class ExportableDeclaration extends Declaration { | ||
/// Whether this declaration is exported. | ||
bool get exported; | ||
} | ||
|
||
abstract class Type extends Node { | ||
Reference emit(); | ||
} | ||
|
||
enum PrimitiveType implements Type { | ||
string('string'), | ||
any('any'), | ||
object('object'), | ||
number('number'), | ||
boolean('boolean'), | ||
undefined('undefined'), | ||
unknown('unknown'); | ||
|
||
const PrimitiveType(this.name); | ||
|
||
@override | ||
final String name; | ||
|
||
@override | ||
ID get id => ID(type: 'type', name: name); | ||
|
||
// TODO(https://github.com/dart-lang/web/pull/386): Configuration options: double and num | ||
@override | ||
Reference emit() { | ||
return switch (this) { | ||
PrimitiveType.string => refer('String'), | ||
PrimitiveType.any => refer('JSAny', 'dart:js_interop'), | ||
PrimitiveType.object => refer('JSObject', 'dart:js_interop'), | ||
PrimitiveType.number => refer('int'), | ||
PrimitiveType.boolean => refer('bool'), | ||
PrimitiveType.undefined => TypeReference((t) => t | ||
..symbol = 'JSAny' | ||
..url = 'dart:js_interop' | ||
..isNullable = true), | ||
PrimitiveType.unknown => TypeReference((t) => t | ||
..symbol = 'JSAny' | ||
..url = 'dart:js_interop' | ||
..isNullable = true) | ||
}; | ||
} | ||
|
||
@override | ||
String? get dartName => null; | ||
} | ||
|
||
// TODO(): Refactor name - not all types can be referred to | ||
// (only specific types) Instead change this | ||
// to represent `typeof` declarations. | ||
// TODO(): Create a shared type for such types that | ||
// can be referred to (i.e namespace, interface, class) | ||
// as a type `ReferrableDeclaration`. | ||
class ReferredType<T extends Declaration> extends Type { | ||
@override | ||
String name; | ||
|
||
@override | ||
ID get id => ID(type: 'type', name: name); | ||
|
||
T declaration; | ||
|
||
List<Type> typeParams; | ||
|
||
ReferredType( | ||
{required this.name, | ||
required this.declaration, | ||
this.typeParams = const []}); | ||
|
||
@override | ||
Reference emit() { | ||
// TODO: implement emit | ||
throw UnimplementedError(); | ||
} | ||
} | ||
|
||
// TODO(https://github.com/dart-lang/web/issues/385): Implement Support for UnionType (including implementing `emit`) | ||
class UnionType extends Type { | ||
List<Type> types; | ||
|
||
UnionType({required this.types}); | ||
|
||
@override | ||
ID get id => ID(type: 'type', name: types.map((t) => t.id).join('|')); | ||
|
||
@override | ||
Reference emit() { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
String? get name => null; | ||
} | ||
|
||
class VariableDeclaration extends NamedDeclaration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We talked briefly about having the IDL use this AST as well, but I'm okay either if you want to do this now as you're adding nodes or later when we have the necessary AST for the IDL generation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add this later when I'm working with nodes similar to those in the IDL. Since we didn't find any instances of global declarations, the next AST declaration would be interfaces |
||
implements ExportableDeclaration { | ||
/// The variable modifier, as represented in TypeScript | ||
VariableModifier modifier; | ||
|
||
@override | ||
String name; | ||
|
||
Type type; | ||
|
||
@override | ||
bool exported; | ||
|
||
VariableDeclaration( | ||
{required this.name, | ||
required this.type, | ||
required this.modifier, | ||
required this.exported}); | ||
|
||
@override | ||
ID get id => ID(type: 'var', name: name); | ||
|
||
@override | ||
Spec emit() { | ||
if (modifier == VariableModifier.$const) { | ||
return Method((m) => m | ||
..name = name | ||
..type = MethodType.getter | ||
..annotations.add(generateJSAnnotation()) | ||
..external = true | ||
..returns = type.emit()); | ||
} else { | ||
// getter and setter -> single variable | ||
return Field((f) => f | ||
..external = true | ||
..name = name | ||
..type = type.emit() | ||
..annotations.add(generateJSAnnotation())); | ||
} | ||
} | ||
} | ||
|
||
enum VariableModifier { let, $const, $var } |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright (c) 2025, 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. | ||
|
||
class ID { | ||
final String type; | ||
final String name; | ||
final int? index; | ||
|
||
const ID({required this.type, required this.name, this.index}); | ||
|
||
bool get isUnnamed => name == 'unnamed'; | ||
|
||
@override | ||
String toString() => '$type#$name${index != null ? '#$index' : ''}'; | ||
} | ||
|
||
class UniqueNamer { | ||
final Set<String> _usedNames; | ||
|
||
UniqueNamer([Iterable<String> used = const <String>[]]) | ||
: _usedNames = used.toSet(); | ||
|
||
static ID parse(String id) { | ||
String? index; | ||
final [type, name, ...ids] = id.split('#'); | ||
if (ids.isEmpty) index = ids.single; | ||
|
||
return ID( | ||
type: type, name: name, index: index == null ? null : int.parse(index)); | ||
} | ||
|
||
/// Adds a [name] to used names. | ||
void markUsed(String name) { | ||
_usedNames.add(name); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright (c) 2025, 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 'dart:js_interop'; | ||
|
||
import '../js/typescript.dart' as ts; | ||
|
||
class ParserResult { | ||
ts.TSProgram program; | ||
Iterable<String> files; | ||
|
||
ParserResult({required this.program, required this.files}); | ||
} | ||
|
||
ParserResult parseDeclarationFiles(Iterable<String> files) { | ||
final program = ts.createProgram(files.jsify() as JSArray<JSString>, | ||
ts.TSCompilerOptions(declaration: true)); | ||
|
||
return ParserResult(program: program, files: files); | ||
} |
Uh oh!
There was an error while loading. Please reload this page.