forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.js
More file actions
1 lines (1 loc) · 13.8 KB
/
Copy pathmain.js
File metadata and controls
1 lines (1 loc) · 13.8 KB
1
define(function(require,exports,module){const AppInit=brackets.getModule("utils/AppInit"),ProjectManager=brackets.getModule("project/ProjectManager"),EditorManager=brackets.getModule("editor/EditorManager"),PreferencesManager=brackets.getModule("preferences/PreferencesManager"),NodeConnector=brackets.getModule("NodeConnector"),Strings=brackets.getModule("strings"),ServerInstaller=require("./ServerInstaller"),Beautifier=require("./Beautifier"),SERVER_ID="python",SUPPORTED_LANGUAGES=["python"];PreferencesManager.definePreference(ServerInstaller.PREF_PYTHON_CODE_INTELLIGENCE,"boolean",!0,{description:Strings.DESCRIPTION_PYTHON_CODE_INTELLIGENCE});let lspClientPromise=null,registered=!1,starting=!1,pendingRepoint=!1,initErrorReported=!1,_repairAttempted=!1,_client=null;function canRun(){return Phoenix.isNativeApp&&NodeConnector.isNodeAvailable()}function loadLSPClient(){return lspClientPromise||(lspClientPromise=new Promise(function(resolve,reject){brackets.getModule(["languageTools/LSPClient"],resolve,function(){setTimeout(function(){brackets.getModule(["languageTools/LSPClient"],resolve,reject)},500)})})),lspClientPromise}function waitForNodeReady(timeout){return new Promise(function(resolve){const deadline=Date.now()+timeout;!function check(){NodeConnector.isNodeReady()?resolve(!0):Date.now()>deadline?resolve(!1):setTimeout(check,300)}()})}async function _registerServer(binaryPath){if(registered)return;const LSPClient=await loadLSPClient(),client=await LSPClient.registerLanguageServer({serverId:SERVER_ID,command:binaryPath,args:["lsp"],languages:SUPPORTED_LANGUAGES,languageIdMap:{python:"python"},initializationOptions:{},workspaceConfiguration:{python:{pyrefly:{typeCheckingMode:"default"}}},suppressStderrPattern:"^\\s*INFO\\b"});client&&(registered=!0,_client=client)}async function start(){if(registered||!canRun())return;const ready=await waitForNodeReady(3e4);if(!ready)return void console.error("[PythonSupport] Node not ready - Python LSP disabled");const state=await ServerInstaller.installedState();state.installed&&state.pinMatches?(await _registerServer(ServerInstaller.getBinaryPlatformPath()),registered||_repairAttempted||Phoenix.isTestWindow||(_repairAttempted=!0,console.error("[PythonSupport] installed server failed to start - reinstalling"),await ServerInstaller.repairInstall())):await ServerInstaller.autoInstall()}function _isPythonDocumentActive(){const editor=EditorManager.getActiveEditor();return!(!editor||!editor.document)&&"python"===editor.document.getLanguage().getId()}function _ensureServerForActiveEditor(){if(canRun()&&_isPythonDocumentActive()&&!1!==PreferencesManager.get(ServerInstaller.PREF_PYTHON_CODE_INTELLIGENCE)){if(!registered){if(starting)return;return starting=!0,pendingRepoint=!1,void start().catch(function(err){initErrorReported||(initErrorReported=!0,window.logger&&window.logger.reportError(err,"[PythonSupport] Python LSP init failed"))}).finally(function(){starting=!1})}pendingRepoint&&(pendingRepoint=!1,loadLSPClient().then(function(LSPClient){LSPClient.changeWorkspaceRoot(SERVER_ID)}))}}canRun()&&loadLSPClient(),AppInit.appReady(function(){canRun()&&(ServerInstaller.init({onInstalled:function(result){_registerServer(result.binaryPath).catch(function(err){window.logger&&window.logger.reportError(err,"[PythonSupport] start after install failed")})}}),Beautifier.init(),EditorManager.on("activeEditorChange.pythonSupport",function(){_ensureServerForActiveEditor()}),_ensureServerForActiveEditor(),ProjectManager.on(ProjectManager.EVENT_PROJECT_OPEN+".pythonSupport",function(){pendingRepoint=!0,_ensureServerForActiveEditor()}),PreferencesManager.on("change",ServerInstaller.PREF_PYTHON_CODE_INTELLIGENCE,function(){!1!==PreferencesManager.get(ServerInstaller.PREF_PYTHON_CODE_INTELLIGENCE)&&_ensureServerForActiveEditor()}))}),exports._ensureServerForActiveEditor=_ensureServerForActiveEditor,exports._getClient=function(){return _client},exports.SERVER_ID=SERVER_ID}),define("Beautifier",function(require,exports,module){const BeautificationManager=brackets.getModule("features/BeautificationManager"),ProjectManager=brackets.getModule("project/ProjectManager"),NodeUtils=brackets.getModule("utils/NodeUtils"),ServerInstaller=require("./ServerInstaller"),FORMAT_TIMEOUT_MS=2e4;async function _runRuffFormat(text,fileNameHint){const state=await ServerInstaller.installedState();if(!state.installed)throw new Error("ruff is not installed yet");const root=ProjectManager.getProjectRoot(),cwd=root?Phoenix.fs.getTauriPlatformPath(root.fullPath):void 0,stdinName=(fileNameHint||"file.py").split("/").pop(),result=await NodeUtils.execFileWithInput(ServerInstaller.getRuffBinaryPlatformPath(),["format","--stdin-filename",stdinName,"-"],{stdinText:text,cwd:cwd,timeoutMs:FORMAT_TIMEOUT_MS});if(0!==result.code)throw new Error(result.stderr||"ruff format exited with "+result.code);return result.stdout}function beautifyTextProvider(textToBeautify,filePathOrFileName){return _runRuffFormat(textToBeautify,filePathOrFileName).then(function(changedText){return{originalText:textToBeautify,changedText:changedText}})}function beautifyEditorProvider(editor){const text=editor.document.getText();return _runRuffFormat(text,editor.document.file.fullPath).then(function(changedText){return{originalText:text,changedText:changedText}})}function init(){BeautificationManager.registerBeautificationProvider(exports,["python"])}exports.init=init,exports.beautifyEditorProvider=beautifyEditorProvider,exports.beautifyTextProvider=beautifyTextProvider}),define("ServerInstaller",function(require,exports,module){const NodeUtils=brackets.getModule("utils/NodeUtils"),NotificationUI=brackets.getModule("widgets/NotificationUI"),TaskManager=brackets.getModule("features/TaskManager"),PreferencesManager=brackets.getModule("preferences/PreferencesManager"),Metrics=brackets.getModule("utils/Metrics"),StringUtils=brackets.getModule("utils/StringUtils"),Strings=brackets.getModule("strings"),_PINS=brackets.config&&brackets.config.lsp_server_pins||{};_PINS.pyrefly&&_PINS.ruff||window.alert("[PythonSupport] lsp_server_pins missing from AppConfig - stale build? Run npm run build.");const PYREFLY_VERSION=_PINS.pyrefly||"1.1.1",RUFF_VERSION=_PINS.ruff||"0.15.20",PREF_PYTHON_CODE_INTELLIGENCE="codeIntelligence.python",UNITS={pyrefly:{pkg:"pyrefly",version:PYREFLY_VERSION},ruff:{pkg:"ruff",version:RUFF_VERSION}};let _onInstalled=null,_inFlight=null,_cancelledThisSession=!1,_cancelRequested=!1,_activeDownload=null,_onlineRetryArmed=!1;function _installDirVfs(unit){return Phoenix.VFS.getAppSupportDir()+"lspServers/"+unit.pkg+"/"}function _binaryRelPath(unit){const exe="win"===brackets.platform?".exe":"";return unit.pkg+"-"+unit.version+".data/scripts/"+unit.pkg+exe}function _binaryVfs(unit){return _installDirVfs(unit)+_binaryRelPath(unit)}function _markerVfs(unit){return _installDirVfs(unit)+"installed.json"}function _binaryPlatformPath(unit){return Phoenix.fs.getTauriPlatformPath(_binaryVfs(unit))}function getBinaryPlatformPath(){return _binaryPlatformPath(UNITS.pyrefly)}function getRuffBinaryPlatformPath(){return _binaryPlatformPath(UNITS.ruff)}async function _unitState(unit){const binExists=await Phoenix.VFS.existsAsync(_binaryVfs(unit));if(binExists)try{const marker=JSON.parse(await Phoenix.VFS.readFileAsync(_markerVfs(unit),"utf8"));return{installed:!0,pinMatches:marker.version===unit.version}}catch(e){return{installed:!0,pinMatches:!1}}const markerExists=await Phoenix.VFS.existsAsync(_markerVfs(unit));return{installed:markerExists,pinMatches:!1}}async function installedState(){const pyrefly=await _unitState(UNITS.pyrefly),ruff=await _unitState(UNITS.ruff);return{installed:pyrefly.installed,pinMatches:pyrefly.pinMatches&&ruff.installed&&ruff.pinMatches}}async function _wheelTag(){const platform=brackets.platform,arch=String(await Phoenix.app.getPlatformArch()||"").toLowerCase(),isX64="x86_64"===arch||"x64"===arch||"amd64"===arch,isArm64="aarch64"===arch||"arm64"===arch;if("win"===platform){if(isX64)return"win_amd64";if(isArm64)return"win_arm64"}else if("mac"===platform){if(isArm64)return"macosx_11_0_arm64";if(isX64)return"macosx_10_12_x86_64"}else if("linux"===platform){if(isX64)return"manylinux_2_17_x86_64.manylinux2014_x86_64";if(isArm64)return"manylinux_2_17_aarch64.manylinux2014_aarch64"}throw new Error("no "+Object.keys(UNITS).join("/")+" build for "+platform+"/"+arch)}async function _resolveWheel(unit,tag){const metaUrl="https://pypi.org/pypi/"+unit.pkg+"/"+unit.version+"/json",response=await fetch(metaUrl);if(!response.ok)throw new Error("PyPI metadata fetch failed with HTTP "+response.status);const meta=await response.json(),wheel=(meta.urls||[]).find(function(u){return u.filename&&u.filename.endsWith(".whl")&&-1!==u.filename.indexOf(tag)});if(!wheel)throw new Error("no "+unit.pkg+" "+unit.version+" wheel for "+tag);return{url:wheel.url,sha256:wheel.digests&&wheel.digests.sha256}}const NETWORK_ERROR_RE=new RegExp("failed to fetch|fetch failed|load failed|ENOTFOUND|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|ENETUNREACH|getaddrinfo|network","i");function _isNetworkError(err){return NETWORK_ERROR_RE.test(err&&err.message||String(err))}function _armOnlineRetry(){_onlineRetryArmed||(_onlineRetryArmed=!0,window.addEventListener("online",function(){_onlineRetryArmed=!1,autoInstall()},{once:!0}))}function _showFailureToast(message){const $tpl=$("<div>").text(message);NotificationUI.createToastFromTemplate(Strings.PYTHON_INSTALL_TITLE,$tpl,{dismissOnClick:!0,toastStyle:NotificationUI.NOTIFICATION_STYLES_CSS_CLASS.SUBTLE,autoCloseTimeS:30,instantOpen:!0})}async function _installUnit(unit,tag,task,pctFrom,pctTo){const wheel=await _resolveWheel(unit,tag);if(_cancelRequested){const cancelErr=new Error("install cancelled");throw cancelErr.cancelled=!0,cancelErr}await Phoenix.VFS.unlinkAsync(_installDirVfs(unit)).catch(function(){});const destDir=Phoenix.fs.getTauriPlatformPath(_installDirVfs(unit)),wheelFile=Phoenix.fs.getTauriPlatformPath(_installDirVfs(unit)+"download.whl"),downloadShare=.85*(pctTo-pctFrom);_activeDownload=NodeUtils.downloadFile(wheel.url,wheelFile,{sha256:wheel.sha256,progress:function(transferred,total){total>0&&task.setProgressPercent(Math.round(pctFrom+transferred/total*downloadShare))}});try{await _activeDownload}finally{_activeDownload=null}await NodeUtils.extractZipFile(wheelFile,destDir),await NodeUtils.setExecutableBits(_binaryPlatformPath(unit)),await Phoenix.VFS.unlinkAsync(_installDirVfs(unit)+"download.whl").catch(function(){});const ok=await Phoenix.VFS.existsAsync(_binaryVfs(unit));if(!ok)throw new Error(unit.pkg+" binary missing after wheel extraction");await Phoenix.VFS.writeFileAsync(_markerVfs(unit),JSON.stringify({version:unit.version},null,4),"utf8"),task.setProgressPercent(pctTo)}async function _doInstall(){const state=await installedState();if(state.installed&&state.pinMatches)return{binaryPath:getBinaryPlatformPath(),upgraded:!1};const upgrading=state.installed;_cancelRequested=!1;let currentUnit=null;const task=TaskManager.addNewTask(Strings.PYTHON_INSTALL_TITLE,Strings.PYTHON_INSTALLING,"<i class='fa-brands fa-python'></i>",{progressPercent:2,onStopClick:function(){_cancelledThisSession=!0,_cancelRequested=!0,_activeDownload&&_activeDownload.cancel().catch(function(){})},onRetryClick:function(){task.close(),installNow()}});task.showStopIcon(Strings.PYTHON_INSTALL_STOP),task.show();try{const tag=await _wheelTag(),pending=[];for(const key of Object.keys(UNITS)){const unitState=await _unitState(UNITS[key]);unitState.installed&&unitState.pinMatches||pending.push(UNITS[key])}task.setProgressPercent(5);const span=90/(pending.length||1);for(let i=0;i<pending.length;i++)currentUnit=pending[i],await _installUnit(pending[i],tag,task,Math.round(5+i*span),Math.round(5+(i+1)*span));return currentUnit=null,task.setProgressPercent(100),task.setMessage(Strings.PYTHON_INSTALL_DONE),task.setSucceded(),setTimeout(task.close,4e3),Metrics.countEvent("lsp","pyInst",upgrading?"upOk":"ok"),{binaryPath:getBinaryPlatformPath(),upgraded:upgrading}}catch(err){const message=err&&err.message||String(err);currentUnit&&await Phoenix.VFS.unlinkAsync(_installDirVfs(currentUnit)).catch(function(){});const cancelled=_cancelRequested||err&&err.cancelled||/cancelled/i.test(message);return cancelled?(Metrics.countEvent("lsp","pyInst","cancel"),task.close(),null):_isNetworkError(err)||!navigator.onLine?(Metrics.countEvent("lsp","pyInst","waitNet"),task.setMessage(Strings.PYTHON_INSTALL_WAITING_NETWORK),setTimeout(task.close,4e3),_armOnlineRetry(),null):(console.error("[PythonSupport] install failed",err),Metrics.countEvent("lsp","pyInst","fail"),window.logger&&window.logger.reportError(err,"[PythonSupport] LSP install failed"),task.setFailed(),task.setMessage(StringUtils.format(Strings.PYTHON_INSTALL_FAILED,message)),task.showRestartIcon(),task.show(),_showFailureToast(StringUtils.format(Strings.PYTHON_INSTALL_FAILED,message)),setTimeout(task.close,3e4),null)}finally{_activeDownload=null}}function installNow(){return _inFlight||(_inFlight=_doInstall().then(function(result){return result&&_onInstalled&&_onInstalled(result),result}).finally(function(){_inFlight=null}))}function autoInstall(){return"undefined"!=typeof Phoenix&&Phoenix.isTestWindow?Promise.resolve(null):_cancelledThisSession||!1===PreferencesManager.get(PREF_PYTHON_CODE_INTELLIGENCE)?Promise.resolve(null):navigator.onLine?installNow():(_armOnlineRetry(),Promise.resolve(null))}async function repairInstall(){for(const key of Object.keys(UNITS))await Phoenix.VFS.unlinkAsync(_installDirVfs(UNITS[key])).catch(function(){});return installNow()}function init(options){_onInstalled=options&&options.onInstalled||null}exports.init=init,exports.installedState=installedState,exports.installNow=installNow,exports.autoInstall=autoInstall,exports.repairInstall=repairInstall,exports.getBinaryPlatformPath=getBinaryPlatformPath,exports.getRuffBinaryPlatformPath=getRuffBinaryPlatformPath,exports.PYREFLY_VERSION=PYREFLY_VERSION,exports.RUFF_VERSION=RUFF_VERSION,exports.PREF_PYTHON_CODE_INTELLIGENCE=PREF_PYTHON_CODE_INTELLIGENCE});