Repository navigation
Expand file tree
/
Copy pathScopeManager.js
More file actions
1 lines (1 loc) · 21.9 KB
/
Copy pathScopeManager.js
File metadata and controls
1 lines (1 loc) · 21.9 KB
1
define(function(require,exports,module){var _=require("thirdparty/lodash");const CodeMirror=require("thirdparty/CodeMirror/lib/codemirror"),DefaultDialogs=require("widgets/DefaultDialogs"),Dialogs=require("widgets/Dialogs"),DocumentManager=require("document/DocumentManager"),EditorManager=require("editor/EditorManager"),FileSystem=require("filesystem/FileSystem"),FileUtils=require("file/FileUtils"),LanguageManager=require("language/LanguageManager"),PreferencesManager=require("preferences/PreferencesManager"),ProjectManager=require("project/ProjectManager"),Strings=require("strings"),StringUtils=require("utils/StringUtils"),InMemoryFile=require("document/InMemoryFile"),IndexingWorker=require("worker/IndexingWorker");IndexingWorker.loadScriptInWorker(`${Phoenix.baseURL}JSUtils/worker/tern-main.js`);var HintUtils=require("./HintUtils"),MessageIds=JSON.parse(require("text!./MessageIds.json")),Preferences=require("./Preferences");let ternEnvironment=[],ternConfigInitDone=!1,pendingTernRequests={},builtinLibraryNames=[],isDocumentDirty=!1,_hintCount=0,currentModule=null,documentChanges=null,preferences=null,deferredPreferences=null;const MAX_HINTS=30,LARGE_LINE_CHANGE=100,LARGE_LINE_COUNT=1e4,OFFSET_ZERO={line:0,ch:0};var config={};function getBuiltins(){return builtinLibraryNames}function initTernEnv(){const builtinDefinitionFiles=JSON.parse(require("text!thirdparty/tern/defs/defs.json"));for(let fileName of builtinDefinitionFiles){let fileUrl=`${Phoenix.baseURL}thirdparty/tern/defs/${fileName}`;console.log("loading tern definition file: ",fileUrl),fetch(fileUrl).then(async contents=>{const ternDefsLibrary=await contents.json();builtinLibraryNames.push(ternDefsLibrary["!name"]),ternEnvironment.push(ternDefsLibrary)}).catch(e=>{console.error("failed to init from tern definition file "+fileName,e)})}}function initPreferences(projectRootPath){const previousRequest=deferredPreferences,request=$.Deferred();deferredPreferences=request,previousRequest&&"pending"===previousRequest.state()&&previousRequest.reject();const pr=ProjectManager.getProjectRoot();if(pr)projectRootPath=pr.fullPath;else if(!projectRootPath)return console.log("initPreferences: projectRootPath has no value. Using Defaults."),preferences=new Preferences,void request.resolve();var path=projectRootPath+Preferences.FILE_NAME;preferences=new Preferences,FileSystem.resolve(path,function(err,file){deferredPreferences===request&&(err?request.resolve():FileUtils.readAsText(file).done(function(text){if(deferredPreferences===request){var configObj=null;try{configObj=JSON.parse(text)}catch(e){console.log("Error parsing preference file: "+path),e instanceof SyntaxError&&console.log(e.message)}preferences=new Preferences(configObj),request.resolve()}}).fail(function(error){deferredPreferences===request&&(preferences=new Preferences,request.resolve())}))})}function ensurePreferences(){deferredPreferences||initPreferences()}function postMessage(msg){currentModule&¤tModule.postMessage(msg)}function isDirectoryExcluded(path){var excludes=preferences.getExcludedDirectories();if(!excludes)return!1;var testPath=ProjectManager.makeProjectRelativeIfPossible(path);return testPath=FileUtils.stripTrailingSlash(testPath),excludes.test(testPath)}function isFileBeingEdited(filePath){var currentEditor=EditorManager.getActiveEditor(),currentDoc=currentEditor&¤tEditor.document;return currentDoc&¤tDoc.file.fullPath===filePath}function isFileExcludedInternal(path){var detectedExclusions=PreferencesManager.get("jscodehints.detectedExclusions")||[];return!(!detectedExclusions||-1===detectedExclusions.indexOf(path))}function isFileExcluded(file){if("."===file.name[0])return!0;var languageID;if(LanguageManager.getLanguageForPath(file.fullPath).getId()!==HintUtils.LANGUAGE_ID)return!0;var excludes=preferences.getExcludedFiles();return!(!excludes||!excludes.test(file.name))||!!isFileExcludedInternal(file.fullPath)}function addPendingRequest(file,offset,type){var requests,key=file+"@"+offset.line+"@"+offset.ch,$deferredRequest;return isFileExcludedInternal(file)?(new $.Deferred).reject().promise():(_.has(pendingTernRequests,key)?requests=pendingTernRequests[key]:(requests={},pendingTernRequests[key]=requests),_.has(requests,type)?$deferredRequest=requests[type]:requests[type]=$deferredRequest=new $.Deferred,$deferredRequest.promise())}function getPendingRequest(file,offset,type){var key=file+"@"+offset.line+"@"+offset.ch;if(_.has(pendingTernRequests,key)){var requests=pendingTernRequests[key],requestType=requests[type];return delete pendingTernRequests[key][type],Object.keys(requests).length||delete pendingTernRequests[key],requestType}}function getResolvedPath(file){return currentModule.getResolvedPath(file)}function getJumptoDef(fileInfo,offset){return postMessage({type:MessageIds.TERN_JUMPTODEF_MSG,fileInfo:fileInfo,offset:offset}),addPendingRequest(fileInfo.name,offset,MessageIds.TERN_JUMPTODEF_MSG)}function filterText(text){ensurePreferences();var newText=text;return text.length>preferences.getMaxFileSize()&&(newText=""),newText}function filterTernFileText(path,text){const languageId=LanguageManager.getLanguageForPath(path).getId();return"html"===languageId||"php"===languageId?"":filterText(text)}function getTextFromDocument(document){return filterTernFileText(document.file.fullPath,document.getText())}function handleRename(response){if(response.error)return;let file,offset,$deferredFindRefs=getPendingRequest(response.file,response.offset,MessageIds.TERN_REFS);$deferredFindRefs&&$deferredFindRefs.resolveWith(null,[response])}function requestJumptoDef(session,document,offset){var path=document.file.fullPath,fileInfo,ternPromise;return{promise:getJumptoDef({type:MessageIds.TERN_FILE_INFO_TYPE_FULL,name:path,offsetLines:0,text:filterText(session.getJavascriptText())},offset)}}function handleJumptoDef(response){var file,offset,$deferredJump=getPendingRequest(response.file,response.offset,MessageIds.TERN_JUMPTODEF_MSG);$deferredJump&&(response.fullPath=getResolvedPath(response.resultFile),$deferredJump.resolveWith(null,[response]))}function handleScopeData(response){var file,offset,$deferredJump=getPendingRequest(response.file,response.offset,MessageIds.TERN_SCOPEDATA_MSG);$deferredJump&&$deferredJump.resolveWith(null,[response])}function getTernHints(fileInfo,offset,isProperty){return postMessage({type:MessageIds.TERN_COMPLETIONS_MSG,fileInfo:fileInfo,offset:offset,isProperty:isProperty}),addPendingRequest(fileInfo.name,offset,MessageIds.TERN_COMPLETIONS_MSG)}function getTernFunctionType(fileInfo,offset){return postMessage({type:MessageIds.TERN_CALLED_FUNC_TYPE_MSG,fileInfo:fileInfo,offset:offset}),addPendingRequest(fileInfo.name,offset,MessageIds.TERN_CALLED_FUNC_TYPE_MSG)}function getFragmentAround(session,start){var minIndent=null,minLine=null,endLine,cm=session.editor._codeMirror,tabSize=cm.getOption("tabSize"),document=session.editor.document,p,min,indent,line;for(p=start.line-1,min=Math.max(0,p-100);p>=min;--p){var fn=(line=session.getLine(p)).search(/\bfunction\b/);fn>=0&&(indent=CodeMirror.countColumn(line,null,tabSize),(null===minIndent||minIndent>indent)&&"keyword"===session.getToken({line:p,ch:fn+1}).type&&(minIndent=indent,minLine=p))}null===minIndent&&(minIndent=0),null===minLine&&(minLine=min);var max=Math.min(cm.lastLine(),start.line+100),endCh=0;for(endLine=start.line+1;endLine<max;++endLine)if((line=cm.getLine(endLine)).length>0&&(indent=CodeMirror.countColumn(line,null,tabSize))<=minIndent){endCh=line.length;break}var from={line:minLine,ch:0},to={line:endLine,ch:endCh};return{type:MessageIds.TERN_FILE_INFO_TYPE_PART,name:document.file.fullPath,offsetLines:from.line,text:document.getRange(from,to)}}function getFileInfo(session,preventPartialUpdates){const languageId=LanguageManager.getLanguageForPath(session.editor.document.file.fullPath).getId();var start=session.getCursor(),end=start,document=session.editor.document,path=document.file.fullPath,result;return result="html"===languageId||"php"===languageId?{type:MessageIds.TERN_FILE_INFO_TYPE_FULL,name:path,text:session.getJavascriptText()}:documentChanges?!preventPartialUpdates&&session.editor.lineCount()>LARGE_LINE_COUNT&&documentChanges.to-documentChanges.from<LARGE_LINE_CHANGE&&documentChanges.from<=start.line&&documentChanges.to>end.line?getFragmentAround(session,start):{type:MessageIds.TERN_FILE_INFO_TYPE_FULL,name:path,text:getTextFromDocument(document)}:{type:MessageIds.TERN_FILE_INFO_TYPE_EMPTY,name:path,text:""},documentChanges=null,result}function getOffset(session,fileInfo,offset){var newOffset;return newOffset=offset?{line:offset.line,ch:offset.ch}:session.getCursor(),fileInfo.type===MessageIds.TERN_FILE_INFO_TYPE_PART&&(newOffset.line=Math.max(0,newOffset.line-fileInfo.offsetLines)),newOffset}function requestGuesses(session,document){var $deferred=$.Deferred(),fileInfo=getFileInfo(session),offset=getOffset(session,fileInfo),promise;return postMessage({type:MessageIds.TERN_GET_GUESSES_MSG,fileInfo:fileInfo,offset:offset}),addPendingRequest(fileInfo.name,offset,MessageIds.TERN_GET_GUESSES_MSG).done(function(guesses){session.setGuesses(guesses),$deferred.resolve()}).fail(function(){$deferred.reject()}),$deferred.promise()}function handleTernCompletions(response){var file=response.file,offset=response.offset,completions=response.completions,properties=response.properties,fnType=response.fnType,type=response.type,error=response.error,$deferredHints=getPendingRequest(file,offset,type);$deferredHints&&(error?$deferredHints.reject():completions?$deferredHints.resolveWith(null,[{completions:completions}]):properties?$deferredHints.resolveWith(null,[{properties:properties}]):fnType&&$deferredHints.resolveWith(null,[fnType]))}function handleGetGuesses(response){var path=response.file,type=response.type,offset,$deferredHints=getPendingRequest(path,response.offset,type);$deferredHints&&$deferredHints.resolveWith(null,[response.properties])}function handleUpdateFile(response){var path=response.path,type=response.type,$deferredHints=getPendingRequest(path,OFFSET_ZERO,type);$deferredHints&&$deferredHints.resolve()}function handleTimedOut(response){var detectedExclusions=PreferencesManager.get("jscodehints.detectedExclusions")||[],filePath=response.file;isFileBeingEdited(filePath)||(-1===detectedExclusions.indexOf(filePath)?(detectedExclusions.push(filePath),PreferencesManager.set("jscodehints.detectedExclusions",detectedExclusions,{location:{scope:"project"}}),Dialogs.showModalDialog(DefaultDialogs.DIALOG_ID_INFO,Strings.DETECTED_EXCLUSION_TITLE,StringUtils.format(Strings.DETECTED_EXCLUSION_INFO,StringUtils.breakableUrl(filePath)),[{className:Dialogs.DIALOG_BTN_CLASS_PRIMARY,id:Dialogs.DIALOG_BTN_OK,text:Strings.OK}])):console.log("JavaScriptCodeHints.handleTimedOut: file already in detectedExclusions array timed out: "+filePath))}function TernModule(){var ternPromise=null,addFilesPromise=null,rootTernDir=null,projectRoot=null,stopAddingFiles=!1,resolvedFiles={},numInitialFiles=0,numResolvedFiles=0,numAddedFiles=0;function getResolvedPath(file){return resolvedFiles[file]}function usingModules(){return numInitialFiles!==numResolvedFiles}function postMessage(msg){addFilesPromise.done(function(){config.debug&&console.debug("Sending message",msg),IndexingWorker.execPeer("invokeTernCommand",msg)})}function _postMessageByPass(msg){ternPromise.done(function(){config.debug&&console.debug("Sending message",msg),IndexingWorker.execPeer("invokeTernCommand",msg)})}function updateTernFile(document){var path=document.file.fullPath;return _postMessageByPass({type:MessageIds.TERN_UPDATE_FILE_MSG,path:path,text:getTextFromDocument(document)}),addPendingRequest(path,OFFSET_ZERO,MessageIds.TERN_UPDATE_FILE_MSG)}function handleTernGetFile(request){function replyWith(name,txt){_postMessageByPass({type:MessageIds.TERN_GET_FILE_MSG,file:name,text:txt})}var name=request.file;function getDocText(filePath){if(filePath.startsWith("/")||(filePath=`/${filePath}`),!FileSystem.isAbsolutePath(filePath)||"//"===filePath.slice(0,2))return(new $.Deferred).reject().promise();var file=FileSystem.getFileForPath(filePath),promise=DocumentManager.getDocumentText(file);return promise.done(function(docText){resolvedFiles[name]=filePath,numResolvedFiles++,replyWith(name,filterTernFileText(filePath,docText))}),promise}function findNameInProject(){var fileName=name.substring(name.lastIndexOf("/")+1);function _fileFilter(entry){return entry.name===fileName}ProjectManager.getAllFiles(_fileFilter).done(function(files){var file;1===(files=files.filter(function(file){var pos;return file.fullPath.length-name.length===file.fullPath.lastIndexOf(name)})).length&&(file=files[0]),file?getDocText(file.fullPath).fail(function(){replyWith(name,"")}):replyWith(name,"")})}isFileExcludedInternal(name)||getDocText(name).fail(function(){getDocText(rootTernDir+name).fail(function(){getDocText(projectRoot+name).fail(findNameInProject)})})}function primePump(path,isUntitledDoc){return _postMessageByPass({type:MessageIds.TERN_PRIME_PUMP_MSG,path:path,isUntitledDoc:isUntitledDoc}),addPendingRequest(path,OFFSET_ZERO,MessageIds.TERN_PRIME_PUMP_MSG)}function handlePrimePumpCompletion(response){var path=response.path,type=response.type,$deferredHints=getPendingRequest(path,OFFSET_ZERO,type);$deferredHints&&$deferredHints.resolve()}function addFilesToTern(files){var maxFileCount=preferences.getMaxFileCount();if(numResolvedFiles+numAddedFiles<maxFileCount){var available=maxFileCount-numResolvedFiles-numAddedFiles;available<files.length&&(files=files.slice(0,available)),numAddedFiles+=files.length,ternPromise.done(function(){var msg={type:MessageIds.TERN_ADD_FILES_MSG,files:files};config.debug&&console.debug("Sending message",msg),IndexingWorker.execPeer("invokeTernCommand",msg)})}else stopAddingFiles=!0;return stopAddingFiles}function addAllFilesAndSubdirectories(dir,doneCallback){FileSystem.resolve(dir,function(err,directory){function visitor(entry){if(!entry.isFile)return!isDirectoryExcluded(entry.fullPath)&&0!==entry.name.indexOf(".")&&!stopAddingFiles;isFileExcluded(entry)||addFilesToTern([entry.fullPath])}err?doneCallback():dir!==FileSystem.getDirectoryForPath(rootTernDir)?directory.visit(visitor,doneCallback):doneCallback()})}function initTernModule(){let moduleDeferred=$.Deferred();function _ternWorkerEventHandler(evt,data){config.debug&&console.log("Message received",data.type);var response=data,type=response.type;type===MessageIds.TERN_COMPLETIONS_MSG||type===MessageIds.TERN_CALLED_FUNC_TYPE_MSG?handleTernCompletions(response):type===MessageIds.TERN_GET_FILE_MSG?handleTernGetFile(response):type===MessageIds.TERN_JUMPTODEF_MSG?handleJumptoDef(response):type===MessageIds.TERN_SCOPEDATA_MSG?handleScopeData(response):type===MessageIds.TERN_REFS?handleRename(response):type===MessageIds.TERN_PRIME_PUMP_MSG?handlePrimePumpCompletion(response):type===MessageIds.TERN_GET_GUESSES_MSG?handleGetGuesses(response):type===MessageIds.TERN_UPDATE_FILE_MSG?handleUpdateFile(response):type===MessageIds.TERN_INFERENCE_TIMEDOUT?handleTimedOut(response):type===MessageIds.TERN_WORKER_READY?moduleDeferred.resolveWith(null):console.error("Tern Module received unknown event: "+(response.log||response))}ternPromise=moduleDeferred.promise(),ternConfigInitDone?(IndexingWorker.off("tern-data"),IndexingWorker.on("tern-data",_ternWorkerEventHandler),IndexingWorker.execPeer("resetTernServer")):(ternConfigInitDone=!0,IndexingWorker.off("tern-data"),IndexingWorker.on("tern-data",_ternWorkerEventHandler),IndexingWorker.execPeer("invokeTernCommand",{type:MessageIds.SET_CONFIG,config:config}).then(()=>{moduleDeferred.resolveWith(null)}))}function initTernServer(dir,files){initTernModule(),numResolvedFiles=0,numAddedFiles=0,stopAddingFiles=!1,numInitialFiles=files.length,ternPromise.done(function(){var msg={type:MessageIds.TERN_INIT_MSG,dir:dir,files:files,env:ternEnvironment,timeout:PreferencesManager.get("jscodehints.inferenceTimeout")};IndexingWorker.execPeer("invokeTernCommand",msg)}),rootTernDir=dir.endsWith("/")?dir:dir+"/"}function canSkipTernInitialization(newFile){return void 0!==resolvedFiles[newFile]}function doEditorChange(session,document,previousDocument){var file=document.file,path=file.fullPath,dir=file.parentPath,pr,addFilesDeferred=$.Deferred(),updateFilePromise;(documentChanges=null,addFilesPromise=addFilesDeferred.promise(),pr=ProjectManager.getProjectRoot()?ProjectManager.getProjectRoot().fullPath:null,canSkipTernInitialization(path))?(isDocumentDirty&&previousDocument?updateTernFile(previousDocument).done(function(){primePump(path,document.isUntitled()),addFilesDeferred.resolveWith(null)}):addFilesDeferred.resolveWith(null),isDocumentDirty=!1):(ternPromise&&previousDocument&&previousDocument.isDirty&&updateTernFile(previousDocument),isDocumentDirty=!1,resolvedFiles={},projectRoot=pr,ensurePreferences(),deferredPreferences.done(function(){var hintsPromise;if(file instanceof InMemoryFile)return initTernServer(pr,[]),void primePump(path,!0).done(function(){addFilesDeferred.resolveWith(null)});FileSystem.resolve(dir,function(err,directory){if(err)return console.error("Error resolving",dir),void addFilesDeferred.resolveWith(null);directory.getContents(function(err,contents){if(err)return console.error("Error getting contents for",directory),void addFilesDeferred.resolveWith(null);var files=contents.filter(function(entry){return entry.isFile&&!isFileExcluded(entry)}).map(function(entry){return entry.fullPath}),hintsPromise;initTernServer(dir,files),primePump(path,!1).done(function(){usingModules()?addFilesDeferred.resolveWith(null):addAllFilesAndSubdirectories(dir,function(){var currentDir=dir+"/";projectRoot&¤tDir!==projectRoot&&0===currentDir.indexOf(projectRoot)?addAllFilesAndSubdirectories(projectRoot,function(){primePump(path,!1),addFilesDeferred.resolveWith(null)}):addFilesDeferred.resolveWith(null)})})})})}).fail(function(){addFilesDeferred.resolveWith(null)}))}function handleEditorChange(session,document,previousDocument){addFilesPromise&&"pending"===addFilesPromise.state()?addFilesPromise.done(function(){handleEditorChange(session,document,previousDocument)}):doEditorChange(session,document,previousDocument)}function resetModule(){function resetTernServer(){IndexingWorker.execPeer("resetTernServer")}addFilesPromise?addFilesPromise.done(resetTernServer).fail(resetTernServer):resetTernServer()}function whenReady(func){addFilesPromise.done(func)}return this.resetModule=resetModule,this.handleEditorChange=handleEditorChange,this.postMessage=postMessage,this.getResolvedPath=getResolvedPath,this.whenReady=whenReady,this}initTernEnv(),DocumentManager.on("dirtyFlagChange",function(event,changedDoc){changedDoc.file.fullPath&&postMessage({type:MessageIds.TERN_UPDATE_DIRTY_FILE,name:changedDoc.file.fullPath,action:changedDoc.isDirty})}),ProjectManager.on("beforeProjectClose",function(){postMessage({type:MessageIds.TERN_CLEAR_DIRTY_FILES_LIST})});var resettingDeferred=null;function _maybeReset(session,document,force){var newTernModule;if(!resettingDeferred){if(!(currentModule.resetForced||force||!config.noReset&&++_hintCount>MAX_HINTS)){var d=new $.Deferred;return d.resolve(currentModule),d.promise()}config.debug&&console.debug("Resetting tern module"),resettingDeferred=new $.Deferred,(newTernModule=new TernModule).handleEditorChange(session,document,null),newTernModule.whenReady(function(){currentModule.resetModule(),currentModule=newTernModule,resettingDeferred.resolve(currentModule),resettingDeferred=null}),_hintCount=0}return resettingDeferred.promise()}function requestParameterHint(session,functionOffset){var $deferredHints=$.Deferred(),fileInfo=getFileInfo(session,!0),offset,fnTypePromise=getTernFunctionType(fileInfo,getOffset(session,fileInfo,functionOffset));return $.when(fnTypePromise).done(function(fnType){session.setFnType(fnType),session.setFunctionCallPos(functionOffset),$deferredHints.resolveWith(null,[fnType])}).fail(function(){$deferredHints.reject()}),$deferredHints.promise()}function requestHints(session,document){var $deferredHints=$.Deferred(),hintPromise,sessionType=session.getType(),fileInfo=getFileInfo(session),offset=getOffset(session,fileInfo,null);return _maybeReset(session,document),hintPromise=getTernHints(fileInfo,offset,sessionType.property),$.when(hintPromise).done(function(completions,fnType){completions.completions?(session.setTernHints(completions.completions),session.setGuesses(null)):(session.setTernHints([]),session.setGuesses(completions.properties)),$deferredHints.resolveWith(null)}).fail(function(){$deferredHints.reject()}),$deferredHints.promise()}function trackChange(changeList){var changed=documentChanges,i;for(null===changed&&(documentChanges=changed={from:changeList[0].from.line,to:changeList[0].from.line},config.debug&&console.debug("ScopeManager: document has changed")),i=0;i<changeList.length;i++){var thisChange=changeList[i],end=thisChange.from.line+(thisChange.text.length-1);thisChange.from.line<changed.to&&(changed.to=changed.to-(thisChange.to.line-end)),end>=changed.to&&(changed.to=end+1),changed.from>thisChange.from.line&&(changed.from=thisChange.from.line)}}function handleFileChange(changeList){isDocumentDirty=!0,trackChange(changeList)}function handleEditorChange(session,document,previousDocument){return currentModule||(currentModule=new TernModule),currentModule.handleEditorChange(session,document,previousDocument)}function handleProjectClose(){currentModule&¤tModule.resetModule()}function handleProjectOpen(projectRootPath){initPreferences(projectRootPath)}function _readyPromise(){return deferredPreferences}function _setConfig(configUpdate){config=brackets._configureJSCodeHints.config,postMessage({type:MessageIds.SET_CONFIG,config:configUpdate})}exports._setConfig=_setConfig,exports._maybeReset=_maybeReset,exports.getBuiltins=getBuiltins,exports.getResolvedPath=getResolvedPath,exports.getTernHints=getTernHints,exports.handleEditorChange=handleEditorChange,exports.requestGuesses=requestGuesses,exports.handleFileChange=handleFileChange,exports.requestHints=requestHints,exports.requestJumptoDef=requestJumptoDef,exports.requestParameterHint=requestParameterHint,exports.handleProjectClose=handleProjectClose,exports.handleProjectOpen=handleProjectOpen,exports._readyPromise=_readyPromise,exports.filterText=filterText,exports.postMessage=postMessage,exports.addPendingRequest=addPendingRequest});