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

Make export default class the main file class in GDScript, add support for subclasses #61

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
946cb1e
Proof of concept, export default is the main file class, others are s…
adamuso Dec 17, 2021
ddcea40
Fix dynamic defs generation and adjust test to use export default, al…
adamuso Dec 18, 2021
2753c88
Fix enum importing without file separation
adamuso Dec 18, 2021
b558ecd
Change inner classes import to preloading
adamuso Dec 18, 2021
5b3418e
Handle extending inner classes from other files
adamuso Dec 18, 2021
6687a9c
Implement anonymous classes
adamuso Dec 18, 2021
5894a26
Fix not taking into account declare classes
adamuso Dec 18, 2021
a544f34
Cleanup tests
adamuso Dec 18, 2021
1e9f87f
Handle inner classes super calls in constructor with arguments
adamuso Dec 19, 2021
bf51a77
Merge remote-tracking branch 'origin/HEAD' into support-for-multiple-…
adamuso Dec 19, 2021
1825ef2
Cleanup commented out code
adamuso Dec 19, 2021
e72f177
Merge branch 'johnfn:main' into support-for-multiple-classes-in-one-file
adamuso Dec 19, 2021
8381679
Fix node path def generation, refactor extending inner/anonymous classes
adamuso Dec 20, 2021
6030bc9
Fix not showing autoload error on non default class
adamuso Dec 21, 2021
ff497da
Update readme
adamuso Dec 21, 2021
c80d179
Merge branch 'main' into support-for-multiple-classes-in-one-file
adamuso Dec 21, 2021
c1f59dd
Fix tests after merging with main
adamuso Dec 21, 2021
f44ae4e
Merge commit '0d007f4b61ad131265d000ebda22f5708ba3ddbe' into support-…
adamuso Dec 23, 2021
fc82ee2
Merge remote-tracking branch 'origin/main' into support-for-multiple-…
adamuso Jan 4, 2022
060ec33
Change class declaration generation, single exported classes are now …
adamuso Jan 4, 2022
b43f26c
Adjust imports and dynamic defs generation
adamuso Jan 4, 2022
ced47d7
Add defs for main and inner attributes
adamuso Jan 4, 2022
e1ea6f2
Revert most test changes related to 'default'
adamuso Jan 4, 2022
b98306f
Revert accidental package-lock update and remove more default from tests
adamuso Jan 4, 2022
630d5ef
Update readme and main class check
adamuso Jan 4, 2022
a61f720
Update classes readme
adamuso Jan 15, 2022
751e2ee
Fix false positive tests when string is expected and add more autoloa…
adamuso Jan 15, 2022
4f65188
Make some error descriptions more user friendly
adamuso Jan 15, 2022
63756f6
Merge branch 'main' into support-for-multiple-classes-in-one-file
adamuso May 24, 2022
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
1 change: 0 additions & 1 deletion .prettierignore

This file was deleted.

105 changes: 87 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,74 @@ To compile all source files once:

## Details and Differences

### Classes
adamuso marked this conversation as resolved.
Show resolved Hide resolved

Creating a file class in GDScript requires TypeScript class to be marked with `export default` keywords.

```ts
export default class MyNode extends Node2D {
constructor() {
super()
print("Hello world")
}
}
```

```gdscript
extends Node2D
class_name MyNode

func _ready():
print("Hello world")
```

File classes can also be anonymous to skip `class_name` generation.

```ts
export default class extends Node2D {
constructor() {
super()
print("Hello world")
}
}
```

```gdscript
extends Node2D

func _ready():
print("Hello world")
```

### Inner classes

To generate inner classes in GDScript file, TypeScript classes should not be marked with `default` keyword.

```ts
export class InnerClass extends Node2D {
constructor() {
super()
print("Hello InnerClass")
}
}

class NotExportedInnerClass {
constructor() {
print("Hello NotExportedInnerClass")
}
}
```

```gdscript
class InnerClass extends Node2D:
func _init().():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .() at the end seems incorrect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that a base constructor is called (here are docs). If base constructor does not have arguments .() can be omitted. Why is it wrong? Does this code not compile or is wrongly generated?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know it looks weird but it really is valid GD syntax!

print("Hello InnerClass")

class NotExportedInnerClass
func _init():
print("Hello NotExportedInnerClass")
```

### `get_node`

`get_node` has been supercharged - it will now autocomplete the names of all
Expand All @@ -53,7 +121,7 @@ get type errors if you break any `get_node` calls!!

ts2gd also provides a way to get any node by name, even the ones it can't verify exist:

```
```ts
this.get_node<Label>("MyLabel")
```

Expand All @@ -73,13 +141,13 @@ Godot decides to put a bunch of enum values into global scope. I think this clut

For instance,

```
```gdscript
Input.is_key_pressed(KEY_W)
```

becomes

```
```ts
adamuso marked this conversation as resolved.
Show resolved Hide resolved
Input.is_key_pressed(KeyList.KEY_SPACE)
```

Expand All @@ -93,13 +161,13 @@ The RPC syntax has been improved.

GDScript:

```
```gdscript
this.rpc("my_rpc_method", "some-argument)
```

TypeScript:

```
```ts
this.my_rpc_method.rpc("some-argument")
```

Expand All @@ -111,7 +179,7 @@ Signals have been improved. All signals now start with `$` and are properties of

This is what connect looks like in ts2gd:

```
```ts
this.my_button.$pressed.connect(() => {
print("Clicked the button!)
})
Expand All @@ -129,7 +197,7 @@ yield this.get_tree().$idle_frame

This is what emit looks like in ts2gd:

```
```ts
class MySignallingClass extends Node2D {
$my_signal!: Signal // ! to avoid the TS error about this signal being unassigned

Expand All @@ -145,9 +213,10 @@ In order to make a class autoload, decorate your class with `@autoload`, and cre

Here's a full example of an autoload class.

```
```ts
// autoload can be specified only on class marked 'export default'
adamuso marked this conversation as resolved.
Show resolved Hide resolved
@autoload
class MyAutoloadClass extends Node2D {
export default class MyAutoloadClass extends Node2D {
public hello = "hi"
}

Expand All @@ -158,8 +227,8 @@ export const MyAutoload = new MyAutoloadClass()

In order to mark an instance variable as `export`, use `@exports`, e.g.:

```
class ExportExample extends Node2D {
```ts
export default class ExportExample extends Node2D {
@exports
public hello = "exported"
}
Expand All @@ -169,9 +238,9 @@ class ExportExample extends Node2D {

In order to mark a script as `tool`, use `@tool`.

```
```ts
@tool
class MyToolScript extends Node2D {
export default class MyToolScript extends Node2D {
// ... do some tool script work here
}
```
Expand All @@ -184,7 +253,7 @@ To mark a method as remotesync or remote, use `@remotesync` and `@remote`, respe

TypeScript sadly has no support for operator overloading.

```
```ts
const v1 = Vector(1, 2)
const v2 = Vector(1, 2);

Expand All @@ -194,13 +263,13 @@ v1.mul(v2); // v1 * v2
v1.div(v2); // v1 / v2
```

The add/sub/mul/div gets compiled into the corresponding arithmatic.
The add/sub/mul/div gets compiled into the corresponding arithmetic.
adamuso marked this conversation as resolved.
Show resolved Hide resolved

### Dictionary

The default TS dictionary (e.g. `const dict = { a: 1 }`) only supports string, number and symbol as keys. If you want anything else, you can just use the Dictionary type, and use `.put` instead of square bracket access.

```
```ts
const myComplexDict: Dictionary<Node2D, int> = todict({})

myComplexDict.put(myNode, 5)
Expand All @@ -210,7 +279,7 @@ myComplexDict.put(myNode, 5)

If you'd like ts2gd to generate the latest TS definitions from Godot, clone the Godot repository and point it at the 3.x tag. Then add the following to your ts2gd.json:

```
```json
"godotSourceRepoPath": "/path/to/your/godot/clone"
```

Expand Down Expand Up @@ -264,7 +333,7 @@ ts2gd generates code with 2 spaces as indent. If Godot keeps changing your .gd f
- [x] strongly type input action names
- [x] handle renames better - delete the old compiled file, etc.
- [ ] refactoring class names doesn't really work right now because i think we need to rename types in tscn files...
- [ ] would be nice to declare multiple classes in the same .ts file and have the compiler sort it out
- [x] would be nice to declare multiple classes in the same .ts file and have the compiler sort it out
adamuso marked this conversation as resolved.
Show resolved Hide resolved
- [x] add a way to install ts2gd as a global command
- [x] ensure that signal arguments match up
- [ ] add a way to use ts2gd via installer rather than command line
Expand Down
28 changes: 14 additions & 14 deletions parse_node/parse_call_expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ v1.distance_to(v1)

export const testArrowScoping: Test = {
ts: `
export class Foo {
export default class Foo {
a() {
const a = () => {};
}
Expand Down Expand Up @@ -513,7 +513,7 @@ d["b"] = 2
export const testConnect: Test = {
expectFail: true,
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
constructor() {
super()

Expand All @@ -537,7 +537,7 @@ func on_body_entered(_body):

export const testConnect2: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
constructor() {
super()

Expand All @@ -559,7 +559,7 @@ func _ready():

export const testConnectWithClosures: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
constructor() {
super()
let x = 1, y = 2;
Expand All @@ -584,7 +584,7 @@ func _ready():
// we intentionally do not capture `this` as self - see comment in parse_arrow_function.ts for rationale
export const testConnectWithClosuresNoThis: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
constructor() {
super()
let x = 1, y = 2;
Expand All @@ -608,7 +608,7 @@ func _ready():

export const testConnectComplex: Test = {
ts: `
export class Test {
export default class Test {
enemies: any;

foo() {
Expand Down Expand Up @@ -643,7 +643,7 @@ d[[1, 2]] = 2

export const testEmitSignal: Test = {
ts: `
export class CityGridCollision extends Area {
export default class CityGridCollision extends Area {
$mouseenter!: Signal<[]>;
test() {
this.$mouseenter.emit()
Expand Down Expand Up @@ -678,7 +678,7 @@ __map(__filter(a, [funcref(self, "__gen"), {}]), [funcref(self, "__gen1"), {}])

export const testRewriteGetNode: Test = {
ts: `
export class Test {
export default class Test {
foo() {
this.get_node('hello')
}
Expand All @@ -694,7 +694,7 @@ func foo():

export const testRewriteGetNode2: Test = {
ts: `
export class Test {
export default class Test {
foo() {
this.get_node_unsafe('hello')
}
Expand Down Expand Up @@ -733,7 +733,7 @@ export const testFunctionNull: Test = {
x(): number | null;
}

export class Test {
export default class Test {
example() {
const thing: Foo = new Foo()
let result = thing.x()
Expand Down Expand Up @@ -782,7 +782,7 @@ x.get_node("Foo")

export const testConnectDirectlyToSig: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
$mysig!: Signal

constructor() {
Expand All @@ -807,7 +807,7 @@ func _ready():

export const testNestedDirectSignalConnect: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
$mysig!: Signal
test!: Test

Expand Down Expand Up @@ -839,7 +839,7 @@ func _ready():

export const testRpcRewrite: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
rpc_me() {

}
Expand Down Expand Up @@ -879,7 +879,7 @@ func _ready():

export const testPassInFunction: Test = {
ts: `
export class Test extends Area2D {
export default class Test extends Area2D {
fn(other: () => void) {
other()
}
Expand Down
Loading