Repository: microsoft/typescript-go (go)

Issue:
block-style directive comments don't work
This errors with `Type 'number' is not assignable to type 'string'`

```ts
/* @ts-ignore */
const s: string = 5
```

Pull request description:
Process directive in multi-line comments
Fixes #495

Patch:
diff --git a/.gitignore b/.gitignore
index bac7db955..1ca52baa8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -142,6 +142,7 @@ dist
 *.dll
 *.so
 *.dylib
+*.wasm
 
 # Test binary, built with `go test -c`
 *.test
diff --git a/cmd/tsgo/enablevtprocessing_other.go b/cmd/tsgo/enablevtprocessing_other.go
new file mode 100644
index 000000000..7d501d3cf
--- /dev/null
+++ b/cmd/tsgo/enablevtprocessing_other.go
@@ -0,0 +1,5 @@
+//go:build !windows
+
+package main
+
+func enableVirtualTerminalProcessing() {}
diff --git a/cmd/tsgo/enablevtprocessing_windows.go b/cmd/tsgo/enablevtprocessing_windows.go
new file mode 100644
index 000000000..d7197595d
--- /dev/null
+++ b/cmd/tsgo/enablevtprocessing_windows.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+	"golang.org/x/sys/windows"
+)
+
+func enableVirtualTerminalProcessing() {
+	hStdout, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
+	if err == nil && hStdout != windows.InvalidHandle {
+		var mode uint32
+		err = windows.GetConsoleMode(windows.Handle(hStdout), &mode)
+		if err == nil {
+			windows.SetConsoleMode(windows.Handle(hStdout), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+		}
+	}
+}
diff --git a/cmd/tsgo/main.go b/cmd/tsgo/main.go
index 9ee6bf077..8f910f85b 100644
--- a/cmd/tsgo/main.go
+++ b/cmd/tsgo/main.go
@@ -121,6 +121,9 @@ func parseArgs() *cliOptions {
 }
 
 func main() {
+	// TypeScript uses ANSI escape sequences which cmd.exe won't parse without enabling virtual terminal processing.
+	enableVirtualTerminalProcessing()
+
 	if args := os.Args[1:]; len(args) > 0 {
 		switch args[0] {
 		case "tsc":
diff --git a/internal/scanner/scanner.go b/internal/scanner/scanner.go
index c3eae52e1..3352825f1 100644
--- a/internal/scanner/scanner.go
+++ b/internal/scanner/scanner.go
@@ -570,11 +570,12 @@ func (s *Scanner) Scan() ast.Kind {
 						s.pos += size
 					}
 				}
-				s.processCommentDirective(s.tokenStart, s.pos)
+				s.processCommentDirective(s.tokenStart, s.pos, false)
 				continue
 			}
 			if s.charAt(1) == '*' {
 				s.pos += 2
+				lastline := s.tokenStart
 				isJSDoc := s.char() == '*' && s.charAt(1) != '/'
 				for {
 					ch = s.char()
@@ -587,21 +588,25 @@ func (s *Scanner) Scan() ast.Kind {
 							s.pos += 2
 							break
 						}
+						s.pos++
 						if ch == '\r' || ch == '\n' {
+							lastline = s.pos
 							s.tokenFlags |= ast.TokenFlagsPrecedingLineBreak
 						}
-						s.pos++
 					} else {
 						commentCh, size := s.charAndSize()
+						s.pos += size
 						if stringutil.IsLineBreak(commentCh) {
+							lastline = s.pos
 							s.tokenFlags |= ast.TokenFlagsPrecedingLineBreak
 						}
-						s.pos += size
 					}
 				}
 				if isJSDoc && s.shouldParseJSDoc() {
 					s.tokenFlags |= ast.TokenFlagsPrecedingJSDocComment
 				}
+
+				s.processCommentDirective(lastline, s.pos, true)
 				continue
 			}
 			if s.charAt(1) == '=' {
@@ -858,9 +863,17 @@ func (s *Scanner) Scan() ast.Kind {
 	}
 }
 
-func (s *Scanner) processCommentDirective(start int, end int) {
+func (s *Scanner) processCommentDirective(start int, end int, multiline bool) {
 	// Skip starting slashes and whitespace
-	pos := start + 2
+	pos := start
+	if multiline {
+		for pos < len(s.text) && (s.text[pos] == '*' || s.text[pos] == '/') {
+			pos++
+		}
+	} else {
+		// Skip "//" for single line comments
+		pos += 2
+	}
 	for pos < len(s.text) && (s.text[pos] == ' ' || s.text[pos] == '\t') {
 		pos++
 	}
diff --git a/internal/vfs/osvfs/os.go b/internal/vfs/osvfs/os.go
index 6cfd867e3..b10a3ded1 100644
--- a/internal/vfs/osvfs/os.go
+++ b/internal/vfs/osvfs/os.go
@@ -36,6 +36,11 @@ var isFileSystemCaseSensitive = func() bool {
 		return false
 	}
 
+	if runtime.GOARCH == "wasm" {
+		// !!! Who knows; this depends on the host implementation.
+		return true
+	}
+
 	// As a proxy for case-insensitivity, we check if the current executable exists under a different case.
 	// This is not entirely correct, since different OSs can have differing case sensitivity in different paths,
 	// but this is largely good enough for our purposes (and what sys.ts used to do with __filename).


Test patch:
diff --git a/testdata/baselines/reference/submodule/conformance/multiline.errors.txt b/testdata/baselines/reference/submodule/conformance/multiline.errors.txt
index f9519a413..ecd31ae45 100644
--- a/testdata/baselines/reference/submodule/conformance/multiline.errors.txt
+++ b/testdata/baselines/reference/submodule/conformance/multiline.errors.txt
@@ -1,28 +1,28 @@
-a.ts(5,12): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
-a.ts(9,12): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
+a.ts(12,1): error TS2578: Unused '@ts-expect-error' directive.
 b.tsx(1,24): error TS2307: Cannot find module 'react' or its corresponding type declarations.
+b.tsx(17,1): error TS2578: Unused '@ts-expect-error' directive.
+b.tsx(28,6): error TS2578: Unused '@ts-expect-error' directive.
+b.tsx(32,1): error TS2578: Unused '@ts-expect-error' directive.
 
 
-==== a.ts (2 errors) ====
+==== a.ts (1 errors) ====
     export const texts: string[] = [];
     
     /**
      @ts-ignore */
     texts.push(100);
-               ~~~
-!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
     
     /**
      @ts-expect-error */
     texts.push(100);
-               ~~~
-!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
     
     /**
      @ts-expect-error */
+    ~~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
     texts.push("100");
     
-==== b.tsx (1 errors) ====
+==== b.tsx (4 errors) ====
     import * as React from "react";
                            ~~~~~~~
 !!! error TS2307: Cannot find module 'react' or its corresponding type declarations.
@@ -42,6 +42,8 @@ b.tsx(1,24): error TS2307: Cannot find module 'react' or its corresponding type
     
         {/*
        @ts-expect-error */}
+    ~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
         <MyComponent foo={100} />
     
         {/*
@@ -53,10 +55,14 @@ b.tsx(1,24): error TS2307: Cannot find module 'react' or its corresponding type
         <MyComponent foo={100} />
     
         {/*@ts-expect-error*/}
+         ~~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
         <MyComponent foo={100} />
     
         {/*
        @ts-expect-error */}
+    ~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
         <MyComponent foo={"hooray"} />
       </div>
     );
diff --git a/testdata/baselines/reference/submodule/conformance/multiline.errors.txt.diff b/testdata/baselines/reference/submodule/conformance/multiline.errors.txt.diff
index 54323caec..db6c8438c 100644
--- a/testdata/baselines/reference/submodule/conformance/multiline.errors.txt.diff
+++ b/testdata/baselines/reference/submodule/conformance/multiline.errors.txt.diff
@@ -1,48 +1,40 @@
 --- old.multiline.errors.txt
 +++ new.multiline.errors.txt
 @@= skipped -0, +0 lines =@@
--a.ts(12,1): error TS2578: Unused '@ts-expect-error' directive.
--b.tsx(32,1): error TS2578: Unused '@ts-expect-error' directive.
-+a.ts(5,12): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
-+a.ts(9,12): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
+ a.ts(12,1): error TS2578: Unused '@ts-expect-error' directive.
 +b.tsx(1,24): error TS2307: Cannot find module 'react' or its corresponding type declarations.
++b.tsx(17,1): error TS2578: Unused '@ts-expect-error' directive.
++b.tsx(28,6): error TS2578: Unused '@ts-expect-error' directive.
+ b.tsx(32,1): error TS2578: Unused '@ts-expect-error' directive.
  
  
--==== a.ts (1 errors) ====
-+==== a.ts (2 errors) ====
-     export const texts: string[] = [];
-     
-     /**
-      @ts-ignore */
-     texts.push(100);
-+               ~~~
-+!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
-     
-     /**
-      @ts-expect-error */
-     texts.push(100);
-+               ~~~
-+!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
-     
-     /**
-      @ts-expect-error */
--    ~~~~~~~~~~~~~~~~~~~~
--!!! error TS2578: Unused '@ts-expect-error' directive.
+@@= skipped -18, +21 lines =@@
+ !!! error TS2578: Unused '@ts-expect-error' directive.
      texts.push("100");
      
- ==== b.tsx (1 errors) ====
+-==== b.tsx (1 errors) ====
++==== b.tsx (4 errors) ====
      import * as React from "react";
 +                           ~~~~~~~
 +!!! error TS2307: Cannot find module 'react' or its corresponding type declarations.
      
      export function MyComponent(props: { foo: string }) {
        return <div />;
-@@= skipped -51, +56 lines =@@
+@@= skipped -18, +20 lines =@@
      
          {/*
         @ts-expect-error */}
--    ~~~~~~~~~~~~~~~~~~~~~~
--!!! error TS2578: Unused '@ts-expect-error' directive.
-         <MyComponent foo={"hooray"} />
-       </div>
-     );
++    ~~~~~~~~~~~~~~~~~~~~~~
++!!! error TS2578: Unused '@ts-expect-error' directive.
+         <MyComponent foo={100} />
+     
+         {/*
+@@= skipped -11, +13 lines =@@
+         <MyComponent foo={100} />
+     
+         {/*@ts-expect-error*/}
++         ~~~~~~~~~~~~~~~~~~~~
++!!! error TS2578: Unused '@ts-expect-error' directive.
+         <MyComponent foo={100} />
+     
+         {/*
diff --git a/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt b/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt
index 616f55d45..66ea5b913 100644
--- a/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt
+++ b/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt
@@ -1,12 +1,12 @@
-ts-expect-error.ts(6,5): error TS2322: Type 'string' is not assignable to type 'number'.
 ts-expect-error.ts(8,1): error TS2578: Unused '@ts-expect-error' directive.
-ts-expect-error.ts(19,5): error TS2322: Type 'string' is not assignable to type 'number'.
+ts-expect-error.ts(11,1): error TS2578: Unused '@ts-expect-error' directive.
 ts-expect-error.ts(21,1): error TS2578: Unused '@ts-expect-error' directive.
+ts-expect-error.ts(24,1): error TS2578: Unused '@ts-expect-error' directive.
+ts-expect-error.ts(28,1): error TS2578: Unused '@ts-expect-error' directive.
 ts-expect-error.ts(31,5): error TS2322: Type 'string' is not assignable to type 'number'.
 ts-expect-error.ts(37,2): error TS2367: This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
 ts-expect-error.ts(39,2): error TS2367: This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
 ts-expect-error.ts(40,2): error TS2367: This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
-ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type 'number'.
 
 
 ==== ts-expect-error.ts (9 errors) ====
@@ -16,8 +16,6 @@ ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type
     /*
      @ts-expect-error additional commenting */
     var invalidCommentedFancyMulti: number = 'nope';
-        ~~~~~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2322: Type 'string' is not assignable to type 'number'.
     
     // @ts-expect-error additional commenting
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -25,6 +23,8 @@ ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type
     var validCommentedFancySingle: string = 'nope';
     
     /* @ts-expect-error additional commenting */
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
     var validCommentedFancyMulti: string = 'nope';
     
     // @ts-expect-error
@@ -33,8 +33,6 @@ ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type
     /*
      @ts-expect-error */
     var invalidCommentedPlainMulti: number = 'nope';
-        ~~~~~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2322: Type 'string' is not assignable to type 'number'.
     
     // @ts-expect-error
     ~~~~~~~~~~~~~~~~~~~
@@ -42,10 +40,14 @@ ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type
     var validCommentedPlainSingle: string = 'nope';
     
     /* @ts-expect-error */
+    ~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
     var validCommentedPlainMulti1: string = 'nope';
     
     /*
     @ts-expect-error */
+    ~~~~~~~~~~~~~~~~~~~
+!!! error TS2578: Unused '@ts-expect-error' directive.
     var validCommentedPlainMulti2: string = 'nope';
     
     var invalidPlain: number = 'nope';
@@ -73,6 +75,4 @@ ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type
     /*
      @ts-expect-error: additional commenting with no whitespace */
     var invalidCommentedFancyMulti: number = 'nope';
-        ~~~~~~~~~~~~~~~~~~~~~~~~~~
-!!! error TS2322: Type 'string' is not assignable to type 'number'.
     
\ No newline at end of file
diff --git a/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt.diff b/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt.diff
deleted file mode 100644
index f7dc0bcfc..000000000
--- a/testdata/baselines/reference/submodule/conformance/ts-expect-error.errors.txt.diff
+++ /dev/null
@@ -1,67 +0,0 @@
---- old.ts-expect-error.errors.txt
-+++ new.ts-expect-error.errors.txt
-@@= skipped -0, +0 lines =@@
-+ts-expect-error.ts(6,5): error TS2322: Type 'string' is not assignable to type 'number'.
- ts-expect-error.ts(8,1): error TS2578: Unused '@ts-expect-error' directive.
--ts-expect-error.ts(11,1): error TS2578: Unused '@ts-expect-error' directive.
-+ts-expect-error.ts(19,5): error TS2322: Type 'string' is not assignable to type 'number'.
- ts-expect-error.ts(21,1): error TS2578: Unused '@ts-expect-error' directive.
--ts-expect-error.ts(24,1): error TS2578: Unused '@ts-expect-error' directive.
--ts-expect-error.ts(28,1): error TS2578: Unused '@ts-expect-error' directive.
- ts-expect-error.ts(31,5): error TS2322: Type 'string' is not assignable to type 'number'.
- ts-expect-error.ts(37,2): error TS2367: This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
- ts-expect-error.ts(39,2): error TS2367: This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
- ts-expect-error.ts(40,2): error TS2367: This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
-+ts-expect-error.ts(47,5): error TS2322: Type 'string' is not assignable to type 'number'.
- 
- 
- ==== ts-expect-error.ts (9 errors) ====
-@@= skipped -15, +15 lines =@@
-     /*
-      @ts-expect-error additional commenting */
-     var invalidCommentedFancyMulti: number = 'nope';
-+        ~~~~~~~~~~~~~~~~~~~~~~~~~~
-+!!! error TS2322: Type 'string' is not assignable to type 'number'.
-     
-     // @ts-expect-error additional commenting
-     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-@@= skipped -7, +9 lines =@@
-     var validCommentedFancySingle: string = 'nope';
-     
-     /* @ts-expect-error additional commenting */
--    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--!!! error TS2578: Unused '@ts-expect-error' directive.
-     var validCommentedFancyMulti: string = 'nope';
-     
-     // @ts-expect-error
-@@= skipped -10, +8 lines =@@
-     /*
-      @ts-expect-error */
-     var invalidCommentedPlainMulti: number = 'nope';
-+        ~~~~~~~~~~~~~~~~~~~~~~~~~~
-+!!! error TS2322: Type 'string' is not assignable to type 'number'.
-     
-     // @ts-expect-error
-     ~~~~~~~~~~~~~~~~~~~
-@@= skipped -7, +9 lines =@@
-     var validCommentedPlainSingle: string = 'nope';
-     
-     /* @ts-expect-error */
--    ~~~~~~~~~~~~~~~~~~~~~~
--!!! error TS2578: Unused '@ts-expect-error' directive.
-     var validCommentedPlainMulti1: string = 'nope';
-     
-     /*
-     @ts-expect-error */
--    ~~~~~~~~~~~~~~~~~~~
--!!! error TS2578: Unused '@ts-expect-error' directive.
-     var validCommentedPlainMulti2: string = 'nope';
-     
-     var invalidPlain: number = 'nope';
-@@= skipped -35, +31 lines =@@
-     /*
-      @ts-expect-error: additional commenting with no whitespace */
-     var invalidCommentedFancyMulti: number = 'nope';
-+        ~~~~~~~~~~~~~~~~~~~~~~~~~~
-+!!! error TS2322: Type 'string' is not assignable to type 'number'.
-