Skip to content

Commit c12b289

Browse files
committed
check lowering target for js decorators in ts
1 parent 1ca08b0 commit c12b289

File tree

3 files changed

+71
-18
lines changed

3 files changed

+71
-18
lines changed

internal/js_parser/js_parser.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6444,15 +6444,21 @@ const (
64446444
func (p *parser) parseDecorators(decoratorScope *js_ast.Scope, classKeyword logger.Range, context decoratorContextFlags) (decorators []js_ast.Decorator) {
64456445
if p.lexer.Token == js_lexer.TAt {
64466446
if p.options.ts.Parse {
6447-
if (context&decoratorInFnArgs) != 0 && p.options.ts.Config.ExperimentalDecorators != config.True {
6448-
p.log.AddErrorWithNotes(&p.tracker, p.lexer.Range(), "Parameter decorators only work when experimental decorators are enabled", []logger.MsgData{{
6449-
Text: "You can enable experimental decorators by adding \"experimentalDecorators\": true to your \"tsconfig.json\" file.",
6450-
}})
6451-
} else if (context & decoratorInClassExpr) != 0 {
6452-
p.lexer.AddRangeErrorWithNotes(p.lexer.Range(), "Experimental decorators can only be used with class declarations in TypeScript",
6453-
[]logger.MsgData{p.tracker.MsgData(classKeyword, "This is a class expression, not a class declaration:")})
6454-
} else if (context & decoratorBeforeClassExpr) != 0 {
6455-
p.log.AddError(&p.tracker, p.lexer.Range(), "Experimental decorators cannot be used in expression position in TypeScript")
6447+
if p.options.ts.Config.ExperimentalDecorators == config.True {
6448+
if (context & decoratorInClassExpr) != 0 {
6449+
p.lexer.AddRangeErrorWithNotes(p.lexer.Range(), "Experimental decorators can only be used with class declarations in TypeScript",
6450+
[]logger.MsgData{p.tracker.MsgData(classKeyword, "This is a class expression, not a class declaration:")})
6451+
} else if (context & decoratorBeforeClassExpr) != 0 {
6452+
p.log.AddError(&p.tracker, p.lexer.Range(), "Experimental decorators cannot be used in expression position in TypeScript")
6453+
}
6454+
} else {
6455+
if (context&decoratorInFnArgs) != 0 && p.options.ts.Config.ExperimentalDecorators != config.True {
6456+
p.log.AddErrorWithNotes(&p.tracker, p.lexer.Range(), "Parameter decorators only work when experimental decorators are enabled", []logger.MsgData{{
6457+
Text: "You can enable experimental decorators by adding \"experimentalDecorators\": true to your \"tsconfig.json\" file.",
6458+
}})
6459+
} else {
6460+
p.markSyntaxFeature(compat.Decorators, p.lexer.Range())
6461+
}
64566462
}
64576463
} else {
64586464
if (context & decoratorInFnArgs) != 0 {

internal/js_parser/js_parser_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,11 @@ func TestAutoAccessors(t *testing.T) {
19831983
}
19841984

19851985
func TestDecorators(t *testing.T) {
1986+
expectPrinted(t, "@x @y class Foo {}", "@x\n@y\nclass Foo {\n}\n")
1987+
expectPrinted(t, "@x @y export class Foo {}", "@x\n@y\nexport class Foo {\n}\n")
1988+
expectPrinted(t, "@x @y export default class Foo {}", "@x\n@y\nexport default class Foo {\n}\n")
1989+
expectPrinted(t, "_ = @x @y class {}", "_ = @x @y class {\n};\n")
1990+
19861991
expectPrinted(t, "class Foo { @x y }", "class Foo {\n @x\n y;\n}\n")
19871992
expectPrinted(t, "class Foo { @x y() {} }", "class Foo {\n @x\n y() {\n }\n}\n")
19881993
expectPrinted(t, "class Foo { @x static y }", "class Foo {\n @x\n static y;\n}\n")
@@ -1997,6 +2002,15 @@ func TestDecorators(t *testing.T) {
19972002

19982003
expectParseError(t, "class Foo { x(@y z) {} }", "<stdin>: ERROR: Parameter decorators are not allowed in JavaScript\n")
19992004
expectParseError(t, "class Foo { @x static {} }", "<stdin>: ERROR: Expected \";\" but found \"{\"\n")
2005+
2006+
errorText := "<stdin>: ERROR: Transforming JavaScript decorators to the configured target environment is not supported yet\n"
2007+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "@dec class Foo {}", errorText)
2008+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "class Foo { @dec x }", errorText)
2009+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "class Foo { @dec x() {} }", errorText)
2010+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "class Foo { @dec accessor x }", errorText)
2011+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "class Foo { @dec static x }", errorText)
2012+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "class Foo { @dec static x() {} }", errorText)
2013+
expectParseErrorWithUnsupportedFeatures(t, compat.Decorators, "class Foo { @dec static accessor x }", errorText)
20002014
}
20012015

20022016
func TestGenerator(t *testing.T) {

internal/js_parser/ts_parser_test.go

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ func expectParseErrorExperimentalDecoratorTS(t *testing.T, contents string, expe
2828
})
2929
}
3030

31+
func expectParseErrorWithUnsupportedFeaturesTS(t *testing.T, unsupportedJSFeatures compat.JSFeature, contents string, expected string) {
32+
t.Helper()
33+
expectParseErrorCommon(t, contents, expected, config.Options{
34+
TS: config.TSOptions{
35+
Parse: true,
36+
},
37+
UnsupportedJSFeatures: unsupportedJSFeatures,
38+
})
39+
}
40+
3141
func expectParseErrorTargetTS(t *testing.T, esVersion int, contents string, expected string) {
3242
t.Helper()
3343
expectParseErrorCommon(t, contents, expected, config.Options{
@@ -1825,15 +1835,6 @@ func TestTSDeclare(t *testing.T) {
18251835
}
18261836

18271837
func TestTSExperimentalDecorator(t *testing.T) {
1828-
expectPrintedTS(t, "@dec class Foo {}", "@dec\nclass Foo {\n}\n")
1829-
expectPrintedTS(t, "class Foo { @dec foo: any }", "class Foo {\n @dec\n foo;\n}\n")
1830-
expectPrintedTS(t, "class Foo { @dec foo(): any {} }", "class Foo {\n @dec\n foo() {\n }\n}\n")
1831-
expectPrintedTS(t, "class Foo { @dec static foo: any }", "class Foo {\n @dec\n static foo;\n}\n")
1832-
expectPrintedTS(t, "class Foo { @dec static foo(): any {} }", "class Foo {\n @dec\n static foo() {\n }\n}\n")
1833-
expectParseErrorTS(t, "class Foo { @dec static {} }", "<stdin>: ERROR: Expected \";\" but found \"{\"\n")
1834-
expectParseErrorTS(t, "class Foo { foo(@dec bar): any }", "<stdin>: ERROR: Parameter decorators only work when experimental decorators are enabled\n"+
1835-
"NOTE: You can enable experimental decorators by adding \"experimentalDecorators\": true to your \"tsconfig.json\" file.\n")
1836-
18371838
// Tests of "declare class"
18381839
expectPrintedExperimentalDecoratorTS(t, "@dec(() => 0) declare class Foo {} {let foo}", "{\n let foo;\n}\n")
18391840
expectPrintedExperimentalDecoratorTS(t, "@dec(() => 0) declare abstract class Foo {} {let foo}", "{\n let foo;\n}\n")
@@ -1971,6 +1972,38 @@ func TestTSExperimentalDecorator(t *testing.T) {
19711972
expectParseErrorExperimentalDecoratorTS(t, "class Foo { @dec static {} }", "<stdin>: ERROR: Expected \";\" but found \"{\"\n")
19721973
}
19731974

1975+
func TestTSDecorators(t *testing.T) {
1976+
expectPrintedTS(t, "@x @y class Foo {}", "@x\n@y\nclass Foo {\n}\n")
1977+
expectPrintedTS(t, "@x @y export class Foo {}", "@x\n@y\nexport class Foo {\n}\n")
1978+
expectPrintedTS(t, "@x @y export default class Foo {}", "@x\n@y\nexport default class Foo {\n}\n")
1979+
expectPrintedTS(t, "_ = @x @y class {}", "_ = @x @y class {\n};\n")
1980+
1981+
expectPrintedTS(t, "class Foo { @x y: any }", "class Foo {\n @x\n y;\n}\n")
1982+
expectPrintedTS(t, "class Foo { @x y(): any {} }", "class Foo {\n @x\n y() {\n }\n}\n")
1983+
expectPrintedTS(t, "class Foo { @x static y: any }", "class Foo {\n @x\n static y;\n}\n")
1984+
expectPrintedTS(t, "class Foo { @x static y(): any {} }", "class Foo {\n @x\n static y() {\n }\n}\n")
1985+
expectPrintedTS(t, "class Foo { @x accessor y: any }", "class Foo {\n @x\n accessor y;\n}\n")
1986+
1987+
expectPrintedTS(t, "class Foo { @x #y: any }", "class Foo {\n @x\n #y;\n}\n")
1988+
expectPrintedTS(t, "class Foo { @x #y(): any {} }", "class Foo {\n @x\n #y() {\n }\n}\n")
1989+
expectPrintedTS(t, "class Foo { @x static #y: any }", "class Foo {\n @x\n static #y;\n}\n")
1990+
expectPrintedTS(t, "class Foo { @x static #y(): any {} }", "class Foo {\n @x\n static #y() {\n }\n}\n")
1991+
expectPrintedTS(t, "class Foo { @x accessor #y: any }", "class Foo {\n @x\n accessor #y;\n}\n")
1992+
1993+
expectParseErrorTS(t, "class Foo { x(@y z) {} }", "<stdin>: ERROR: Parameter decorators only work when experimental decorators are enabled\n"+
1994+
"NOTE: You can enable experimental decorators by adding \"experimentalDecorators\": true to your \"tsconfig.json\" file.\n")
1995+
expectParseErrorTS(t, "class Foo { @x static {} }", "<stdin>: ERROR: Expected \";\" but found \"{\"\n")
1996+
1997+
errorText := "<stdin>: ERROR: Transforming JavaScript decorators to the configured target environment is not supported yet\n"
1998+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "@dec class Foo {}", errorText)
1999+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec x }", errorText)
2000+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec x() {} }", errorText)
2001+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec accessor x }", errorText)
2002+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec static x }", errorText)
2003+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec static x() {} }", errorText)
2004+
expectParseErrorWithUnsupportedFeaturesTS(t, compat.Decorators, "class Foo { @dec static accessor x }", errorText)
2005+
}
2006+
19742007
func TestTSTry(t *testing.T) {
19752008
expectPrintedTS(t, "try {} catch (x: any) {}", "try {\n} catch (x) {\n}\n")
19762009
expectPrintedTS(t, "try {} catch (x: unknown) {}", "try {\n} catch (x) {\n}\n")

0 commit comments

Comments
 (0)