瀏覽代碼

Adds a vfs project

Orta 4 年之前
父節點
當前提交
166e63b991
共有 5 個文件被更改,包括 113 次插入26 次删除
  1. 24 0
      package-lock.json
  2. 1 0
      package.json
  3. 3 2
      src/tsWorker.ts
  4. 30 23
      test/custom-worker.html
  5. 55 1
      test/custom-worker.js

+ 24 - 0
package-lock.json

@@ -4,6 +4,15 @@
   "lockfileVersion": 1,
   "lockfileVersion": 1,
   "requires": true,
   "requires": true,
   "dependencies": {
   "dependencies": {
+    "@typescript/vfs": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.2.0.tgz",
+      "integrity": "sha512-3YhBC+iyngEHjEedSAWk9rbJHoBwa2cd4h/tzb2TXmZc2CUclTl3x5AQRKNoRqm7t+X9PGTc2q2/Dpray/O4mA==",
+      "dev": true,
+      "requires": {
+        "debug": "^4.1.1"
+      }
+    },
     "buffer-from": {
     "buffer-from": {
       "version": "1.1.1",
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
       "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@@ -16,6 +25,15 @@
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "dev": true
       "dev": true
     },
     },
+    "debug": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+      "dev": true,
+      "requires": {
+        "ms": "^2.1.1"
+      }
+    },
     "monaco-editor-core": {
     "monaco-editor-core": {
       "version": "0.20.0",
       "version": "0.20.0",
       "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.20.0.tgz",
       "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.20.0.tgz",
@@ -45,6 +63,12 @@
         }
         }
       }
       }
     },
     },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
     "requirejs": {
     "requirejs": {
       "version": "2.3.6",
       "version": "2.3.6",
       "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
       "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "url": "https://github.com/Microsoft/monaco-typescript/issues"
     "url": "https://github.com/Microsoft/monaco-typescript/issues"
   },
   },
   "devDependencies": {
   "devDependencies": {
+    "@typescript/vfs": "^1.2.0",
     "monaco-editor-core": "^0.20.0",
     "monaco-editor-core": "^0.20.0",
     "monaco-languages": "^1.10.0",
     "monaco-languages": "^1.10.0",
     "monaco-plugin-helpers": "^1.0.2",
     "monaco-plugin-helpers": "^1.0.2",

+ 3 - 2
src/tsWorker.ts

@@ -10,6 +10,7 @@ import { IExtraLibs } from './monaco.contribution';
 
 
 import IWorkerContext = monaco.worker.IWorkerContext;
 import IWorkerContext = monaco.worker.IWorkerContext;
 
 
+
 export class TypeScriptWorker implements ts.LanguageServiceHost, monaco.languages.typescript.TypeScriptWorker {
 export class TypeScriptWorker implements ts.LanguageServiceHost, monaco.languages.typescript.TypeScriptWorker {
 
 
 	// --- model sync -----------------------
 	// --- model sync -----------------------
@@ -36,7 +37,7 @@ export class TypeScriptWorker implements ts.LanguageServiceHost, monaco.language
 		return models.concat(Object.keys(this._extraLibs));
 		return models.concat(Object.keys(this._extraLibs));
 	}
 	}
 
 
-	private _getModel(fileName: string): monaco.worker.IMirrorModel | null {
+	_getModel(fileName: string): monaco.worker.IMirrorModel | null {
 		let models = this._ctx.getMirrorModels();
 		let models = this._ctx.getMirrorModels();
 		for (let i = 0; i < models.length; i++) {
 		for (let i = 0; i < models.length; i++) {
 			if (models[i].uri.toString() === fileName) {
 			if (models[i].uri.toString() === fileName) {
@@ -271,7 +272,7 @@ export function create(ctx: IWorkerContext, createData: ICreateData): TypeScript
 				throw new Error(`The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self`)
 				throw new Error(`The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self`)
 			}
 			}
 			// @ts-ignore - The throw validates this
 			// @ts-ignore - The throw validates this
-			TSWorkerClass = self.customTSWorkerFactory(TypeScriptWorker)
+			TSWorkerClass = self.customTSWorkerFactory(TypeScriptWorker, ts, libFileMap)
 		}
 		}
 	}
 	}
 
 

+ 30 - 23
test/custom-worker.html

@@ -20,6 +20,7 @@
 <div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
 <div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
 <h3>Custom webworker</h3>
 <h3>Custom webworker</h3>
 <button id="logDTS">Log DTS</button>
 <button id="logDTS">Log DTS</button>
+<button id="getAST">Print AST to console</button>
 
 
 <script>
 <script>
 	var paths = {
 	var paths = {
@@ -181,35 +182,41 @@
 		'vs/language/typescript/monaco.contribution'
 		'vs/language/typescript/monaco.contribution'
 	], () => {
 	], () => {
 
 
-    monaco.languages.typescript.typescriptDefaults.setWorkerOptions({ customWorkerPath: "http://localhost:5000/test/custom-worker.js" })
-    monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ target: 99, jsx: 1, allowNonTsExtensions: true, declaration: true })
-
-		var editor = monaco.editor.create(document.getElementById('container'), {
-			value: localStorage.getItem("code") || getDefaultCode(),
-			language: 'typescript',
-      lightbulb: { enabled: true }
-    });
+	monaco.languages.typescript.typescriptDefaults.setWorkerOptions({ customWorkerPath: "http://localhost:5000/test/custom-worker.js" })
+	monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ target: 99, jsx: 1, allowNonTsExtensions: true, declaration: true, noLibCheck: true })
 
 
+	var editor = monaco.editor.create(document.getElementById('container'), {
+		value: localStorage.getItem("code") || getDefaultCode(),
+		language: 'typescript',
+		lightbulb: { enabled: true }
+	});
 
 
+	editor.onDidChangeModelContent(() => {
+		const code = editor.getModel().getValue()
+		localStorage.setItem("code", code)
+	});
 
 
-		editor.onDidChangeModelContent(() => {
-			const code = editor.getModel().getValue()
-			localStorage.setItem("code", code)
-		});
+	document.getElementById('resetBtn').onclick = () => {
+		editor.setValue(getDefaultCode());
+	};
 
 
-		document.getElementById('resetBtn').onclick = () => {
-      editor.setValue(getDefaultCode());
-    };
+	document.getElementById('logDTS').onclick = async () => {
+		const model = editor.getModel()
+		const worker = await monaco.languages.typescript.getTypeScriptWorker()
+		const thisWorker = await worker(model.uri)
+		const dts = await thisWorker.getDTSEmitForFile(model.uri.toString())
+		console.log(dts)
+	};
 
 
-    document.getElementById('logDTS').onclick = async () => {
-      const model = editor.getModel()
-      const worker = await monaco.languages.typescript.getTypeScriptWorker()
-      const thisWorker = await worker(model.uri)
-      const dts = await thisWorker.getDTSEmitForFile(model.uri.toString())
-      console.log(dts)
-		};
+	document.getElementById('getAST').onclick = async () => {
+		const model = editor.getModel()
+		const worker = await monaco.languages.typescript.getTypeScriptWorker()
+		const thisWorker = await worker(model.uri)
+		const ast = await thisWorker.printAST(model.uri.toString())
+		console.log(ast)
+	};
 
 
-	});
+});
 </script>
 </script>
 </body>
 </body>
 </html>
 </html>

+ 55 - 1
test/custom-worker.js

@@ -1,4 +1,19 @@
-self.customTSWorkerFactory = (TypeScriptWorker) => {
+// This example uses @typescript/vfs to create a virtual TS program
+// which can do work on a bg thread.
+
+importScripts("https://unpkg.com/@typescript/vfs@1.3.0/dist/vfs.globals.js")
+
+/**
+ *
+ * @param {import("../src/tsWorker").TypeScriptWorker} TypeScriptWorker
+ * @param {import("typescript")} ts
+ * @param {Record<string, string>} libFileMap
+ *
+ */
+const worker = (TypeScriptWorker, ts, libFileMap) => {
+  /** @type { import("@typescript/vfs") } */
+  const tsvfs = globalThis.tsvfs
+
   return class MonacoTSWorker extends TypeScriptWorker {
   return class MonacoTSWorker extends TypeScriptWorker {
 
 
     // Adds a custom function to the webworker
     // Adds a custom function to the webworker
@@ -8,5 +23,44 @@ self.customTSWorkerFactory = (TypeScriptWorker) => {
       return (firstDTS && firstDTS.text) || ""
       return (firstDTS && firstDTS.text) || ""
     }
     }
 
 
+    async printAST(fileName) {
+      console.log("Creating virtual TS project")
+      const compilerOptions = this.getCompilationSettings()
+      const fsMap = new Map()
+      for (const key of Object.keys(libFileMap)) {
+        fsMap.set(key, "/" + libFileMap[key])
+      }
+
+      const thisCode =  await this.getScriptText(fileName)
+      fsMap.set("index.ts", thisCode)
+
+      console.log("Starting up TS program")
+      const system = tsvfs.createSystem(fsMap)
+      const host = tsvfs.createVirtualCompilerHost(system, compilerOptions, ts)
+
+      const program = ts.createProgram({
+        rootNames: [...fsMap.keys()],
+        options: compilerOptions,
+        host: host.compilerHost,
+      })
+
+      // Now I can look at the AST for the .ts file too
+      const mainSrcFile = program.getSourceFile("index.ts")
+      let miniAST = "SourceFile"
+
+      const recurse = (parent, depth) => {
+        if (depth > 5) return
+        ts.forEachChild(parent, node => {
+          const spaces = "  ".repeat(depth + 1)
+          miniAST += `\n${spaces}${ts.SyntaxKind[node.kind]}`
+          recurse(node, depth + 1)
+        })
+      }
+      recurse(mainSrcFile, 0)
+      return miniAST
+    }
+
   }
   }
 }
 }
+
+self.customTSWorkerFactory = worker