vuejs / vetur

Vue tooling for VS Code.
https://vuejs.github.io/vetur/
MIT License
5.75k stars 594 forks source link

Vue language Server is breaking in typescript 5.x #3689

Open axetroy opened 1 year ago

axetroy commented 1 year ago

Info

Vetur initialized
c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:888
`,sCe=new Map;function yPt(e){let{createLanguageServiceSourceFile:t,updateLanguageServiceSourceFile:r}=QD(e,sCe);e.createLanguageServiceSourceFile=t,e.updateLanguageServiceSourceFile=r}s(yPt,"patchTS");function xPt(e){return{allowNonTsExtensions:!0,allowJs:!0,lib:["lib.dom.d.ts","lib.es2017.d.ts"],target:e.ScriptTarget.Latest,moduleResolution:e.ModuleResolutionKind.NodeJs,module:e.ModuleKind.CommonJS,jsx:e.JsxEmit.Preserve,allowSyntheticDefaultImports:!0,experimentalDecorators:!0}}s(xPt,"getDefaultCompilerOptions");var tb={};function iN(e,t,r){yPt(e);let n,i=t.getVueVersion(),o=1,a=new Map,l=new Map,c=new Map,u=new Map,p=new mf,d,f,g,v,S,T,C,k,A;F();function w(){let P={...xPt(e),...d.options};return P.allowNonTsExtensions=!0,P}s(w,"getCompilerOptions");function F(){i=t.getVueVersion(),o=1,a=new Map,l=new Map,c=new Map,u=new Map,p=new mf,d=CPt(e,t.getProjectRoot(),t.getTsConfigPath());let P=d.fileNames;On.logDebug(`Initializing ServiceHost with ${P.length} files: ${JSON.stringify(P)}`),f=new Set(P),g=nN(e,f),v=w(),S=B(v),T=B({...v,noUnusedLocals:!1,noUnusedParameters:!1,allowJs:!0,checkJs:!0}),C=e.createDocumentRegistry(!0),k=e.createLanguageService(S,C),A=wPt(e.createLanguageService(T,C))}s(F,"init");function D(P,X){let Y=A.getProgram();if(Y){let $=Y.getSourceFile(P+".template");if($)return{source:$.getText(),sourceMapNodesString:sP(tb[P],X,$.getText())}}return{source:"",sourceMapNodesString:""}}s(D,"queryVirtualFileInfo");function _(P,X){var I;let Y=Rt(P.uri),$=sm(P.uri);if(l.has(Y)||(Y.endsWith(".vue")||Y.endsWith(".vue.template"))&&f.add($),wc(Y)){let H=(I=l.get(Y))==null?void 0:I.version;f.add($),X&&sCe.set($,X),H!==P.version&&(l.set(Y,P),a.set(Y,(a.get(Y)||0)+1),o++)}return{templateService:A,templateSourceMap:tb}}s(_,"updateCurrentVirtualVueTextDocument");function O(P){let X=Rt(P.uri),Y=sm(P.uri);if(l.has(X)||(X.endsWith(".vue")||X.endsWith(".vue.template"))&&f.add(Y),!n||P.uri!==n.uri||P.version!==n.version){n=r.refreshAndGet(P);let $=l.get(X);$&&n.languageId!==$.languageId&&(k.dispose(),k=e.createLanguageService(S)),l.set(X,n),f.add(Y),a.set(X,(a.get(X)||0)+1),o++}return{service:k,scriptDoc:n}}s(O,"updateCurrentVueTextDocument");function j(P){if(P===t.getTsConfigPath()||i!==t.getVueVersion()){On.logInfo(`refresh ts language service when ${P} changed.`),F();return}let X=d.configFileSpecs,Y=e.isExcludedFile;if(Y&&X&&Y(P,X,t.getProjectRoot(),!0,t.getProjectRoot()))return;On.logInfo(`update ${P} in ts language service.`);let $=a.get(P)||0;a.set(P,$+1),o++,u.has(P)&&u.delete(P)}s(j,"updateExternalDocument");function ne(){return Array.from(f)}s(ne,"getFileNames");function B(P){return{getProjectVersion:()=>o.toString(),getCompilationSettings:()=>P,getScriptFileNames:()=>Array.from(f),getScriptVersion(X){if(X.includes("node_modules")||X===rb)return"0";let Y=hs(X),$=a.get(Y);return $?$.toString():"0"},getScriptKind(X){if(X.includes("node_modules"))return e.getScriptKindFromFileName(X);if(xc(X)){let Y=xn.file(X),$=hs(X),I=l.get($);return I||(I=r.refreshAndGet(sn.create(Y.toString(),"vue",0,e.sys.readFile(X)||"")),l.set($,I),f.add(X)),SPt(e,I.languageId)}else return wc(X)||X===rb?e.ScriptKind.TS:e.getScriptKindFromFileName(X)},getDirectories:g.getDirectories,directoryExists:g.directoryExists,fileExists:g.fileExists,readFile:g.readFile,readDirectory(X,Y,$,I,H){let z=Y&&Y.concat([".vue"]);return g.readDirectory(X,z,$,I,H)},resolveModuleNames(X,Y){return X.map(I=>{if(I===ZD)return{resolvedFileName:rb,extension:e.Extension.Ts,isExternalLibraryImport:!0};let H=p.getCache(I,Y);if(H)return H;if(!xc(I)){let Z=e.resolveModuleName(I,Y,P,e.sys).resolvedModule;return Z&&p.setCache(I,Y,Z),Z}let z=e.resolveModuleName(I,Y,P,g).resolvedModule;if(z)if(z.resolvedFileName.endsWith(".vue.ts")){let Z=z.resolvedFileName.slice(0,-3),ie=xn.file(Z),se=hs(Z),q=l.get(se);q||(q=r.refreshAndGet(sn.create(ie.toString(),"vue",0,e.sys.readFile(Z)||"")),l.set(se,q),f.add(Z));let G=q.languageId==="typescript"?e.Extension.Ts:q.languageId==="tsx"?e.Extension.Tsx:e.Extension.Js,Q={resolvedFileName:Z,extension:G};return p.setCache(I,Y,Q),Q}else return p.setCache(I,Y,z),z})},getScriptSnapshot:X=>{if(X.includes("node_modules")){if(c.has(X))return c.get(X);let H=e.sys.readFile(X)||"",z={getText:(Z,ie)=>H.substring(Z,ie),getLength:()=>H.length,getChangeRange:()=>{}};return c.set(X,z),z}if(X===rb){let H=i===0?eN:i===1?tN:rN;return{getText:(z,Z)=>H.substring(z,Z),getLength:()=>H.length,getChangeRange:()=>{}}}let Y=hs(X);if(wc(Y)){let H=l.get(Y),z=H?H.getText():"";return{getText:(Z,ie)=>z.substring(Z,ie),getLength:()=>z.length,getChangeRange:()=>{}}}if(!xc(Y)){if(u.has(Y))return u.get(Y);let H=e.sys.readFile(Y)||"",z={getText:(Z,ie)=>H.substring(Z,ie),getLength:()=>H.length,getChangeRange:()=>{}};return u.set(Y,z),z}let $=l.get(Y),I="";if($)I=$.getText();else{let H=e.sys.readFile(Y)||"";I=zx(H)}return{getText:(H,z)=>I.substring(H,z),getLength:()=>I.length,getChangeRange:()=>{}}},getCurrentDirectory:()=>t.getProjectRoot(),getDefaultLibFileName:e.getDefaultLibFilePath,getNewLine:()=>vPt,useCaseSensitiveFileNames:()=>!0}}return s(B,"createLanguageServiceHost"),{queryVirtualFileInfo:D,updateCurrentVirtualVueTextDocument:_,updateCurrentVueTextDocument:O,updateExternalDocument:j,getFileNames:ne,getComplierOptions:()=>v,getLanguageService:()=>k,dispose:()=>{k.dispose()}}}s(iN,"getServiceHost");function wPt(e){let t=new Set(ek);return{...e,getCompletionsAtPosition(r,n,i){let o=e.getCompletionsAtPosition(r,n,i);if(o)return o.isMemberCompletion?o:{...o,entries:o.entries.filter(a=>t.has(a.name))}}}}s(wPt,"patchTemplateService");function _Pt(e,t){let r=["node_modules","**/node_modules/*"],n=e.findConfigFile(t,e.sys.fileExists,".gitignore");if(!n)return r;try{let i=rCe.default.globs(n),a=(0,iCe.flatten)(i.filter(l=>l.type==="ignore").map(l=>l.patterns)).filter(l=>!l.startsWith("!"));return r.concat(a)}catch{return r}}s(_Pt,"defaultIgnorePatterns");function SPt(e,t){return t==="typescript"?e.ScriptKind.TS:t==="tsx"?e.ScriptKind.TSX:e.ScriptKind.JS}s(SPt,"getScriptKind");function CPt(e,t,r){let n=r?(0,nCe.dirname)(r):t,i=r&&e.readConfigFile(r,e.sys.readFile).config||{include:["**/*.vue"],exclude:_Pt(e,n)};return e.parseJsonConfigFileContent(i,e.sys,n,{},r,void 0,[{extension:"vue",isMixedContent:!0,scriptKind:e.ScriptKind.Deferred}])}s(CPt,"getParsedConfig");var BCe=pt(jCe());var ob=class{constructor(t){this.env=t}getId(){return"sass"}doComplete(t,r){let n=Mp(t,r,"sass",this.env.getConfig().emmet);if(n){let i=n.items.map(o=>({...o,sortText:0+o.label}));return{isIncomplete:n.isIncomplete,items:i}}else return{isIncomplete:!1,items:[]}}format(t,r,n){var i,o;return this.env.getConfig().vetur.format.defaultFormatter.sass==="sass-formatter"?[St.replace(r,BCe.SassFormatter.Format(t.getText(r),{...n,...(o=(i=this.env.getConfig())==null?void 0:i.sass)==null?void 0:o.format}))]:[]}onDocumentRemoved(t){}dispose(){}};s(ob,"SassLanguageMode");zn();var uEe=pt(lV());zn();function jN(e,t){let r=(0,uEe.default)(e),n=Ur.create(t.line+1,t.character+1);return r.find(({loc:i,type:o})=>i.start.line<=n.line&&i.end.line>=n.line&&i.start.column<=n.character&&i.end.column>n.character&&o!=="newline")||null}s(jN,"findTokenAtPosition");var pEe=s(e=>({start:Ur.create(e.start.line-1,e.start.column-1),end:Ur.create(e.end.line-1,e.end.column-1)}),"locToRange");function BN(e,t,r,n){let i=ms(10,60,o=>r.refreshAndGet(o).getSingleLanguageDocument("pug"));return{getId:()=>"pug",format(o,a,l){if(e.getConfig().vetur.format.defaultFormatter.pug==="none")return[];let{value:c,range:u}=BNt(o,a);return KR(t,c,Rt(o.uri),"pug",u,e.getConfig().vetur.format,!1)},findDefinition(o,a){let l=i.refreshAndGet(o),c=jN(l.getText(),a);if(!c||c.type!=="tag")return[];let u=n==null?void 0:n.getInfo(o);return u?jy(u,c.val):[]},onDocumentRemoved(){},dispose(){}}}s(BN,"getPugMode");function BNt(e,t){let r=e.getText(),n=t;if(t){let i=e.offsetAt(t.start),o=e.offsetAt(t.end);r=r.substring(i,o)}else n=Vt.create(Ur.create(0,0),e.positionAt(r.length));return{value:r,range:n}}s(BNt,"getValueAndRange");var Ou=pt(mi()),cV=require("os"),hEe=require("path");zn();function WN(e,t){let r,n,i,o=s(()=>{},"getTSScriptTarget");function a(u,p,d){let f=u.getText().slice(0,p)+d+u.getText().slice(p);return sn.create(u.uri,u.languageId,u.version+1,f)}s(a,"createMockDoc");function l(u,p,d,f,g){var T,C;let v={label:u+"Vue",data:{languageId:"vue-html",uri:p.uri,offset:d,source:f.data.path}};return(C=(T=i(p,v))==null?void 0:T.additionalTextEdits)==null?void 0:C.map(k=>(k.newText=k.newText.replace(u+"Vue",g),k))}s(l,"getJSImportEdits");function c(u,p){let d=1;for(;u.some(f=>[p,p.toLowerCase(),(0,Ou.kebabCase)(p)].includes(f.name));)p=`${p}${d++}`;return(0,Ou.upperFirst)(p)}return s(c,"getNoDuplicateComponentName"),{setGetConfigure(u){r=u},setGetFilesFn(u){n=u},setGetJSResolve(u){i=u},setGetTSScriptTarget(u){o=u},doComplete(u){var f,g,v;let p=r();if(!p.vetur.completion.autoImport)return[];if(!n||!i||!t)return[];let d=(v=(g=(f=t.getInfo(u))==null?void 0:f.componentInfo.childComponents)==null?void 0:g.map(S=>{var T;return(T=S.definition)==null?void 0:T.path}))!=null?v:[];return n().filter(S=>!d.includes(S)).map(S=>{let T=(0,hEe.basename)(S,".vue");p.vetur.completion.tagCasing==="kebab"&&(T=(0,Ou.kebabCase)(T));let C=`
                                                                                                                                                  ^

TypeError: Cannot set property createLanguageServiceSourceFile of #<Object> which has only a getter
    at patchTS (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:888:147)
    at getServiceHost (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:888:551)
    at hb.init (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:895:1259)
    at createProjectService (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:895:8486)
    at _T.getProjectService (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:896:10802)
    at async _T.doValidate (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:896:18216)
    at async _T.validateTextDocument (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:896:18090)
[INFO ] Find node_modules paths in c:\Users\Admin\gpm\192.168.0.254\digimaple\cloudoc_im_pc - 2074ms
[INFO ] Loaded typescript@5.0.2 from c:\Users\Admin\gpm\192.168.0.254\digimaple\cloudoc_im_pc\node_modules\typescript for tsdk.
[Info  - 10:27:53] Connection to server got closed. Server will restart.
Vetur initialized
[INFO ] Find node_modules paths in c:\Users\Admin\gpm\192.168.0.254\digimaple\cloudoc_im_pc - 1869ms
[INFO ] Loaded typescript@5.0.2 from c:\Users\Admin\gpm\192.168.0.254\digimaple\cloudoc_im_pc\node_modules\typescript for tsdk.
[INFO ] Loaded prettier@2.6.1 from c:\Users\Admin\gpm\192.168.0.254\digimaple\cloudoc_im_pc\node_modules\prettier.
[INFO ] Loaded bundled @starptech/prettyhtml.
[INFO ] Loaded bundled prettier-eslint.
[INFO ] Loaded bundled prettier-tslint.
[INFO ] Loaded bundled stylus-supremacy.
[INFO ] Loaded bundled @prettier/plugin-pug.
[Error - 10:28:00] Request textDocument/documentSymbol failed.
  Message: Request textDocument/documentSymbol failed with message: Cannot set property createLanguageServiceSourceFile of #<Object> which has only a getter
  Code: -32603 

Problem

The loading status in status bar is always loading.

Because the Vue Language Server can not start correctely

Reproducible Case

axetroy commented 1 year ago

And I found this in sourcecode

https://github.com/vuejs/vetur/blob/96aaa707f8ca629f0883c57a47adb0e58995936d/server/src/services/typescriptService/serviceHost.ts#L33-L38

Maybe typescript 5.0 got a breaking change.

And I debug in vscode and print to console, make confirm this

createLanguageServiceSourceFile: [Getter],
axetroy commented 1 year ago

I research the code of Typescript.

  var __defProp = Object.defineProperty;
  var __getOwnPropNames = Object.getOwnPropertyNames;
  var __esm = (fn, res) => function __init() {
    return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
  };
  var __commonJS = (cb, mod) => function __require() {
    return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  };
  var __export = (target, all) => {
    for (var name in all)
      __defProp(target, name, { get: all[name], enumerable: true });
  };

  // src/typescript/_namespaces/ts.ts
  var ts_exports3 = {};
  __export(ts_exports3, {
   // ...
   createLanguageServiceSourceFile: () => createLanguageServiceSourceFile
 })

It use Object.defineProperty to define a exports getter.

so, The changes below should fix this issue

  var __export = (target, all) => {
    for (var name in all)
-     __defProp(target, name, { get: all[name], enumerable: true });
+     __defProp(target, name, { get: all[name], enumerable: true, configurable: true });
  };
- (tsModule as any).createLanguageServiceSourceFile = createLanguageServiceSourceFile; 
+ Object.defineProperty(tsModule, 'createLanguageServiceSourceFile', { get: () => createLanguageServiceSourceFile, enumerable: true })
- (tsModule as any).updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; 
+ Object.defineProperty(tsModule, 'updateLanguageServiceSourceFile', { get: () => updateLanguageServiceSourceFile, enumerable: true })
axetroy commented 1 year ago

I try to patch the Typescript exports in node_modules

but I found this doesn't work because tsModule is find from package env.

It may use vscode build-in typescript version, while it great then 5.0.0, vetur will crash and unusable

~Temporary Solution~

if you are using typescript(or your vscode build-in typescript) that lower then 5.0.0, the extension still working.

othersize:

replace the code like before I write

and use it in .vscode/setting.json

"typescript.tsdk": "node_modules\\typescript\\lib"

restart Vue language Server and you will get this error:

TypeError: Cannot read properties of undefined (reading 'length')
    at F (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:888:963)
    at getServiceHost (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:888:655)
    at hb.init (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:895:1259)
    at createProjectService (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:895:8486)
    at _T.getProjectService (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:896:10802)
    at async _T.doValidate (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:896:18216)
    at async _T.validateTextDocument (c:\Users\Admin\.vscode-server\extensions\octref.vetur-0.37.3\server\dist\vls.js:896:18090)
[Info  - 14:40:39] Connection to server got closed. Server will restart.
[Error - 14:40:39] Request textDocument/documentSymbol failed.

It comes from:

https://github.com/vuejs/vetur/blob/96aaa707f8ca629f0883c57a47adb0e58995936d/server/src/services/typescriptService/serviceHost.ts#L137-L142

initialProjectFiles is undefined

This can not be fixed with a little patch.

Conclusion

It can not be fix from vscode extension, it should be fix from upstream(Typescript) and then update vetur to typescript@^5.0.0

Rollback your vscode to older version to make it works again

@yoyo930021 This is my investigation. Are you interested in investigating and solving it? The vetur has completely failed to work on my vscode.

yoyo930021 commented 1 year ago

I think you can change title for issue. I will try to fix it when I have time.

asmaloney commented 1 year ago

Just wanted to confirm that this is reproducible. When using TypeScript 5.x, vetur would hang. Switching back to 4.9.4 fixed it.

axetroy commented 1 year ago

The exported API is no longer defined as a "configurable" object

https://github.com/microsoft/TypeScript/issues/52847

ref: https://github.com/mrmckeb/typescript-plugin-css-modules/pull/211/files

yoyo930021 commented 1 year ago

Vetur relies deeply on this API. We use it to inject Vue.extends to Vue SFC script block. It will be quite troublesome for fix it.

mustafaekim commented 1 year ago

if I understand correctly, we cannot yet use Vetur with typescript 5.*, is this the current state?

curlykay9527 commented 1 year ago

Anything new on this issue?

kaangokdemir commented 1 year ago

I also wonder if there is a temporary solution to use TypeScript 5 with Vetur since I'm dependent on Vue.extend Volar is unsuitable in my case. 👀

stouch commented 1 year ago

Same probem, I just want to make Vetur works in my vue 2 project ..