define(function(require,exports,module){var CodeMirror=require("thirdparty/CodeMirror/lib/codemirror"),Async=require("utils/Async"),DocumentManager=require("document/DocumentManager"),AppInit=require("utils/AppInit"),EditorManager=require("editor/EditorManager"),HTMLUtils=require("language/HTMLUtils"),LanguageManager=require("language/LanguageManager"),ProjectManager=require("project/ProjectManager"),TokenUtils=require("utils/TokenUtils"),IndexingWorker=require("worker/IndexingWorker"),_=require("thirdparty/lodash");const MAX_CONTENT_LENGTH=10485760,SELECTOR="selector",PROP_NAME="prop.name",PROP_VALUE="prop.value",IMPORT_URL="import.url";var _bracketPairs={"{":"}","[":"]","(":")"},_invertedBracketPairs=_.invert(_bracketPairs);function isCSSPreprocessorFile(filePath){var languageId=LanguageManager.getLanguageForPath(filePath).getId();return"less"===languageId||"scss"===languageId}function _hasNonWhitespace(text){return/\S/.test(text)}function _getContextState(ctx){if(!ctx||!ctx.token)return null;var state=ctx.token.state.localState||ctx.token.state;return state.htmlState?state=ctx.token.state.htmlState:!state.context&&ctx.token.state.html&&ctx.token.state.html.localState&&(state=ctx.token.state.html.localState),state}function _isInPropName(ctx){var state=_getContextState(ctx),lastToken;return!(!state||!state.context||"comment"===ctx.token.type)&&("{"===(lastToken=state.context.type)||"rule"===lastToken||"block"===lastToken)}function _isInPropValue(ctx){function isInsideParens(context){return!("parens"!==context.type||!context.prev)&&("prop"===context.prev.type||isInsideParens(context.prev))}var state=_getContextState(ctx);return!!(state&&state.context&&state.context.prev&&"comment"!==ctx.token.type)&&("prop"===state.context.type&&("rule"===state.context.prev.type||"block"===state.context.prev.type)||isInsideParens(state.context))}function _isInAtRule(ctx){var state=_getContextState(ctx);return!(!state||!state.context)&&"atBlock_parens"===state.context.type}function createInfo(context,offset,name,index,values,isNewItem,range){var ruleInfo={context:context||"",offset:offset||0,name:name||"",index:-1,values:[],isNewItem:!0===isNewItem,range:range};return context!==PROP_VALUE&&context!==SELECTOR&&context!==IMPORT_URL||(ruleInfo.index=index,ruleInfo.values=values),ruleInfo}function _getPropNameInfo(ctx){var propName="",offset=TokenUtils.offsetInToken(ctx),tokenString=ctx.token.string,excludedCharacters=[";","{","}"];if("property"===ctx.token.type||"property error"===ctx.token.type||"tag"===ctx.token.type)propName=tokenString,TokenUtils.movePrevToken(ctx)&&_hasNonWhitespace(ctx.token.string)&&-1===excludedCharacters.indexOf(ctx.token.string)&&(propName=ctx.token.string+tokenString,offset+=ctx.token.string.length);else if("meta"===ctx.token.type||"-"===tokenString)propName=tokenString,!TokenUtils.moveNextToken(ctx)||"property"!==ctx.token.type&&"property error"!==ctx.token.type&&"tag"!==ctx.token.type||(propName+=ctx.token.string);else{if(_hasNonWhitespace(tokenString)&&-1===excludedCharacters.indexOf(tokenString))return createInfo();var testPos={ch:ctx.pos.ch+1,line:ctx.pos.line},testToken=ctx.editor.getTokenAt(testPos,!0);if("property"===testToken.type||"property error"===testToken.type||"tag"===testToken.type)propName=testToken.string,offset=0;else if("meta"===testToken.type||"-"===testToken.string)return ctx.pos=testPos,ctx.token=testToken,_getPropNameInfo(ctx)}return""===propName&&(offset=0),createInfo(PROP_NAME,offset,propName)}function _getPropNameStartingFromPropValue(ctx){var ctxClone=$.extend({},ctx),propName="";do{if(":"!==ctxClone.token.string&&!_isInPropValue(ctxClone))return""}while(":"!==ctxClone.token.string&&TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken,ctxClone));return":"!==ctxClone.token.string||!TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken,ctxClone)||"property"!==ctxClone.token.type&&"property error"!==ctxClone.token.type||(propName=ctxClone.token.string,TokenUtils.movePrevToken(ctxClone)&&"meta"===ctxClone.token.type&&(propName=ctxClone.token.string+propName)),propName}function _getPrecedingPropValues(ctx){for(var lastValue="",curValue,propValues=[];":"!==ctx.token.string&&TokenUtils.movePrevToken(ctx)&&":"!==ctx.token.string&&_isInPropValue(ctx);)curValue=ctx.token.string,""!==lastValue&&(curValue+=lastValue),ctx.token.string.length>0&&!ctx.token.string.match(/\S/)||","===ctx.token.string?lastValue=curValue:(lastValue="",0===propValues.length||curValue.match(/,\s*$/)?propValues.push(curValue):propValues[propValues.length-1]=curValue+propValues[propValues.length-1]);return propValues.length>0&&propValues.reverse(),propValues}function _getSucceedingPropValues(ctx,currentValue){for(var lastValue=currentValue,propValues=[];";"!==ctx.token.string&&"}"!==ctx.token.string&&TokenUtils.moveNextToken(ctx)&&";"!==ctx.token.string&&"}"!==ctx.token.string;){if(!_isInPropValue(ctx)){lastValue="";break}""===lastValue?lastValue=ctx.token.string.trim():lastValue.length>0&&(ctx.token.string.length>0&&!ctx.token.string.match(/\S/)?(lastValue+=ctx.token.string,propValues.push(lastValue),lastValue=""):","===ctx.token.string?lastValue+=ctx.token.string:lastValue&&lastValue.match(/,$/)?(propValues.push(lastValue),lastValue=ctx.token.string.length>0?ctx.token.string:""):lastValue+=ctx.token.string)}return lastValue.length>0&&propValues.push(lastValue),propValues}function _getRangeForPropValue(startCtx,endCtx){for(var range={start:{},end:{}};TokenUtils.moveNextToken(startCtx)&&!_hasNonWhitespace(startCtx.token.string););for(;";"===endCtx.token.string||"}"===endCtx.token.string||!_hasNonWhitespace(endCtx.token.string);)TokenUtils.movePrevToken(endCtx);return range.start=_.clone(startCtx.pos),range.start.ch=startCtx.token.start,range.end=_.clone(endCtx.pos),range.end.ch=endCtx.token.end,range}function _getRuleInfoStartingFromPropValue(ctx,editorParam){var editor=editorParam._codeMirror||editorParam,contextDoc=editor.document||editor.doc,propNamePos=$.extend({},ctx.pos),backwardPos=$.extend({},ctx.pos),forwardPos=$.extend({},ctx.pos),propNameCtx=TokenUtils.getInitialContext(editor,propNamePos),backwardCtx,forwardCtx,lastValue="",propValues=[],index=-1,offset=TokenUtils.offsetInToken(ctx),canAddNewOne=!1,testPos={ch:ctx.pos.ch+1,line:ctx.pos.line},testToken=editor.getTokenAt(testPos,!0),propName,range;return(propName=_getPropNameStartingFromPropValue(propNameCtx))?(propValues=_getPrecedingPropValues(backwardCtx=TokenUtils.getInitialContext(editor,backwardPos)),lastValue="",":"===ctx.token.string?(index=0,canAddNewOne=!0):(index=propValues.length-1,","===ctx.token.string?(propValues[index]+=ctx.token.string,index++,canAddNewOne=!0):(index=index<0?0:index+1,ctx.token.string.match(/\S/)?lastValue=ctx.token.string:(canAddNewOne=!0,index>0&&(propValues[index-1]+=ctx.token.string.substr(0,offset))))),canAddNewOne&&(offset=0,contextDoc.getLine(ctx.pos.line).length>ctx.pos.ch&&(0===testToken.string.length||testToken.string.match(/\S/))&&(canAddNewOne=!1)),forwardCtx=TokenUtils.getInitialContext(editor,forwardPos),range=(propValues=propValues.concat(_getSucceedingPropValues(forwardCtx,lastValue))).length?_getRangeForPropValue(backwardCtx,forwardCtx):{start:_.clone(ctx.pos),end:_.clone(ctx.pos)},index===propValues.length&&(canAddNewOne=!0),createInfo(PROP_VALUE,offset,propName,index,propValues,canAddNewOne,range)):createInfo()}function _getImportUrlInfo(ctx,editor){var backwardPos=$.extend({},ctx.pos),forwardPos=$.extend({},ctx.pos),backwardCtx,forwardCtx,index=0,propValues=[],offset=TokenUtils.offsetInToken(ctx);if(ctx.token.type&&"string"!==ctx.token.type)return createInfo();for(backwardCtx=TokenUtils.getInitialContext(editor._codeMirror,backwardPos),propValues[0]=backwardCtx.token.string;TokenUtils.movePrevToken(backwardCtx)&&("def"!==backwardCtx.token.type||"@import"!==backwardCtx.token.string)&&(!backwardCtx.token.type||"atom"===backwardCtx.token.type||"url"===backwardCtx.token.string);)propValues[0]=backwardCtx.token.string+propValues[0],offset+=backwardCtx.token.string.length;if("def"!==backwardCtx.token.type||"@import"!==backwardCtx.token.string)return createInfo();forwardCtx=TokenUtils.getInitialContext(editor._codeMirror,forwardPos);do{if(!TokenUtils.moveNextToken(forwardCtx)){if("("===forwardCtx.token.string)break;return createInfo()}propValues[0]+=forwardCtx.token.string}while(")"!==forwardCtx.token.string&&""!==forwardCtx.token.string);return createInfo(IMPORT_URL,offset,"",0,propValues,!1)}function getInfoAtPos(editor,constPos){var pos=$.extend({},constPos),ctx=TokenUtils.getInitialContext(editor._codeMirror,pos),mode=editor.getModeForSelection();if("css"!==mode&&"text/x-scss"!==mode&&"text/x-less"!==mode)return createInfo();if(ctx.token.state.htmlState&&(!ctx.token.state.localMode||"css"!==ctx.token.state.localMode.name)){var tagInfo=HTMLUtils.getTagInfo(editor,pos,!0),offset=tagInfo.position.offset,_contextCM=new CodeMirror(function(){},{value:"{"+tagInfo.attr.value.replace(/(^")|("$)/g,""),mode:"css"});ctx=TokenUtils.getInitialContext(_contextCM,{line:0,ch:offset+1})}return _isInPropName(ctx)?_getPropNameInfo(ctx):_isInPropValue(ctx)?_getRuleInfoStartingFromPropValue(ctx,ctx.editor):_isInAtRule(ctx)?_getImportUrlInfo(ctx,editor):createInfo()}function getCompleteSelectors(info,useGroup){if(info.parentSelectors){var completeSelectors=info.parentSelectors+" / ";return useGroup&&info.selectorGroup?completeSelectors+=info.selectorGroup:completeSelectors+=info.selector,completeSelectors}return useGroup&&info.selectorGroup?info.selectorGroup:info.selector}const _RE_PAREN_SEMI=/\([^)]+;/,_RE_OPEN_BRACE=/\{/,_RE_FOLLOWED_BY_PSEUDO=/\}:(enabled|disabled|checked|indeterminate|link|visited|hover|active|focus|target|lang|root|nth-|first-|last-|only-|empty|not)/,_RE_VAR_INTERPOLATED=/[@#]\{\S+\}(\s*:|.*;)/;function extractAllSelectors(text,documentMode){var state,lines,lineCount,token,style,stream,line,selectors=[],mode=CodeMirror.getMode({indentUnit:2},documentMode||"css"),currentSelector="",currentLevel=0,ruleStartChar=-1,ruleStartLine=-1,selectorStartChar=-1,selectorStartLine=-1,selectorGroupStartLine=-1,selectorGroupStartChar=-1,declListStartLine=-1,declListStartChar=-1,escapePattern=new RegExp("\\\\[^\\\\]+","g"),validationPattern=new RegExp("\\\\([a-f0-9]{6}|[a-f0-9]{4}(\\s|\\\\|$)|[a-f0-9]{2}(\\s|\\\\|$)|.)","i"),_parseRuleList,_lineFlagsFor=null,_lineFlags={},_parentScanLevel=-1,_parentScanFrom=0,_firstUnset=0;function _lineFlag(name,compute){return _lineFlagsFor!==stream.string&&(_lineFlagsFor=stream.string,_lineFlags={}),void 0===_lineFlags[name]&&(_lineFlags[name]=compute(_lineFlagsFor)),_lineFlags[name]}function _hasStream(){for(;stream.eol();){if(++line>=lineCount)return!1;_hasNonWhitespace(currentSelector)&&(currentSelector+=" "),stream=new CodeMirror.StringStream(lines[line])}return!0}function _firstToken(){return state=CodeMirror.startState(mode),lines=CodeMirror.splitLines(text),0!==(lineCount=lines.length)&&(line=0,stream=new CodeMirror.StringStream(lines[line]),!!_hasStream()&&(style=mode.token(stream,state),token=stream.current(),!0))}function _nextToken(){return stream.start=stream.pos,!!_hasStream()&&(style=mode.token(stream,state),token=stream.current(),!0)}function _firstTokenSkippingWhitespace(){if(!_firstToken())return!1;for(;!_hasNonWhitespace(token);)if(!_nextToken())return!1;return!0}function _nextTokenSkippingWhitespace(){if(!_nextToken())return!1;for(;!_hasNonWhitespace(token);)if(!_nextToken())return!1;return!0}function _isStartComment(){return/^\/[\/\*]/.test(token)}function _parseComment(){if(!/^\/\//.test(token))for(;!/\*\/$/.test(token)&&_nextToken(););}function _nextTokenSkippingComments(){if(!_nextToken())return!1;for(;_isStartComment();)if(_parseComment(),!_nextToken())return!1;return!0}function _skipToClosingBracket(startChar){var skippedText="",unmatchedBraces=0;for(startChar||(startChar="{");;){if(-1!==token.indexOf(startChar)&&-1===token.indexOf(_bracketPairs[startChar]))unmatchedBraces++;else if(token===_bracketPairs[startChar]&&--unmatchedBraces<=0)return skippedText+=token;if(skippedText+=token,!_nextTokenSkippingComments())return skippedText}}function _maybeProperty(){return/^-(moz|ms|o|webkit)-$/.test(token)||"top"!==state.state&&"block"!==state.state&&"pseudo"!==state.state&&_lineFlag("semi",function(str){return-1!==str.indexOf(";")})&&!_lineFlag("parenSemi",function(str){return _RE_PAREN_SEMI.test(str)})}function _skipProperty(){for(var prevToken="";";"!==token&&(!(/[#@]\{$/.test(token)||"{"===token&&/[#@]$/.test(prevToken))||(_skipToClosingBracket("{"),"}"===token&&_nextToken(),";"!==token));){if("{"===token||"}"===token)return!1;if(prevToken=token,!_nextTokenSkippingComments())break}return!0}function _getParentSelectors(){var j;for(_parentScanLevel!==currentLevel&&(_parentScanLevel=currentLevel,_parentScanFrom=0),j=selectors.length-1;j>=_parentScanFrom;j--)if(-1===selectors[j].declListEndLine&&selectors[j].levelselectors.length-1&&(_firstUnset=selectors.length-1),currentSelector=""}return selectorStartChar=-1,!0}function _parseSelectorList(level){if(selectorGroupStartLine=_lineFlag("comma",function(str){return-1!==str.indexOf(",")})?line:-1,selectorGroupStartChar=stream.start,!_parseSelector(stream.start,level))return!1;for(;","===token;){if(!_nextTokenSkippingComments())return!1;if(!_parseSelector(stream.start,level))return!1}return!0}function _parseDeclarationList(level){var j,selectorGroup,sgLine;if(declListStartLine=Math.min(line,lineCount-1),declListStartChar=stream.start,-1!==selectorGroupStartLine){for(selectorGroup="",sgLine=selectorGroupStartLine;sgLine<=declListStartLine;sgLine++){var startChar=0,endChar=lines[sgLine].length;sgLine===selectorGroupStartLine?startChar=selectorGroupStartChar:selectorGroup+=" ",sgLine===declListStartLine&&(endChar=declListStartChar),selectorGroup+=lines[sgLine].substring(startChar,endChar).trim()}selectorGroup=selectorGroup.trim()}for(j=selectors.length-1;j>=_firstUnset;j--)if(selectors[j].level===level){if(-1!==selectors[j].declListEndLine)break;selectors[j].declListStartLine=declListStartLine,selectors[j].declListStartChar=declListStartChar,selectorGroup&&(selectors[j].selectorGroup=selectorGroup)}var nested=!0;do{selectorGroupStartLine=-1,selectorGroupStartChar=-1,ruleStartLine=-1,ruleStartChar=-1,nested||currentLevel>0&¤tLevel===level&&(currentLevel--,"}"===token&&_nextTokenSkippingWhitespace()),"{"===token&&_nextTokenSkippingWhitespace(),nested=_parseRuleList(void 0,currentLevel+1);var closedAll=!0;for(j=selectors.length-1;j>=_firstUnset;j--){if(selectors[j].level0&¤tLevel===level)}function includeCommentInNextRule(){return-1===ruleStartChar&&!(stream.start>0&&-1!==lines[line].substr(0,stream.start).indexOf("}"))}function _isStartAtRule(){return/^@/.test(token)&&!/^@mixin/i.test(token)&&"@"!==token}function _followedByPseudoSelector(){return _lineFlag("pseudo",function(str){return _RE_FOLLOWED_BY_PSEUDO.test(str)})}function _isVariableInterpolatedProperty(){return _lineFlag("varInterp",function(str){return _RE_VAR_INTERPOLATED.test(str)})&&!_followedByPseudoSelector()}function _parseAtRule(level){if(ruleStartLine=-1,ruleStartChar=-1,selectorStartLine=-1,selectorStartChar=-1,selectorGroupStartLine=-1,selectorGroupStartChar=-1,/@media/i.test(token)){for(;"{"!==token;)if(!_nextTokenSkippingComments())return;if(!_nextTokenSkippingWhitespace())return;currentLevel<=level&¤tLevel++,_parseRuleList("}",currentLevel+1),currentLevel>0&¤tLevel--}else for(;";"!==token;){if("{"===token)return void _skipToClosingBracket("{");if(!_nextTokenSkippingComments())return}}function _parseRule(level){return!!_parseSelectorList(level)&&(_parseDeclarationList(level),!0)}return _parseRuleList=function(escapeToken,level){for(;!escapeToken||token!==escapeToken;){if(_isVariableInterpolatedProperty()){if(!_skipProperty())return!1}else if(_isStartAtRule())_parseAtRule(level);else if(_isStartComment())includeCommentInNextRule()&&(ruleStartChar=stream.start,ruleStartLine=line),_parseComment();else if(_maybeProperty()){if(!_skipProperty())return!1}else{if(!_parseRule(void 0===level?0:level)&&level>0)return!1;if(level>0)return!0;ruleStartChar=-1,ruleStartLine=-1}if(!_nextTokenSkippingWhitespace())break}return!0},_firstTokenSkippingWhitespace()&&_parseRuleList(),selectors}function _stripAtRules(selector){return 0===(selector=selector.trim()).indexOf("@")?"":selector}function _getSelectorInFinalCSSForm(selectorArray){var finalSelectorArray=[""],parentSelectorArray=[],group=[];return _.forEach(selectorArray,function(selector){selector=_stripAtRules(selector),group=selector.split(","),parentSelectorArray=[],_.forEach(group,function(cs){var ampersandIndex=cs.indexOf("&");_.forEach(finalSelectorArray,function(ps){-1===ampersandIndex?(cs=_stripAtRules(cs),ps.length&&cs.length&&(ps+=" "),ps+=cs):ps=_stripAtRules(cs.replace(/&/g,ps)),parentSelectorArray.push(ps)})}),finalSelectorArray=parentSelectorArray}),finalSelectorArray.join(", ")}function _findAllMatchingSelectorsInText(text,selector,mode){var allSelectors=extractAllSelectors(text,mode),result=[],classOrIdSelector="."===selector[0]||"#"===selector[0];"."===selector[0]&&(selector="\\"+selector),classOrIdSelector||(selector="(^|[\\s>+~])"+selector);var re=new RegExp(selector+"(\\[[^\\]]*\\]|:{1,2}[\\w-()]+|\\.[\\w-]+|#[\\w-]+)*\\s*$",classOrIdSelector?"":"i");return allSelectors.forEach(function(entry){var actualSelector=entry.selector;if(-1!==entry.selector.indexOf("&")&&entry.parentSelectors){var selectorArray=entry.parentSelectors.split(" / ");selectorArray.push(entry.selector),actualSelector=_getSelectorInFinalCSSForm(selectorArray)}-1!==actualSelector.search(re)?result.push(entry):classOrIdSelector||/\*\s*$/.test(actualSelector)&&result.push(entry)}),result}function _addSelectorsToResults(resultSelectors,selectorsToAdd,sourceDoc,lineOffset){selectorsToAdd.forEach(function(selectorInfo){resultSelectors.push({name:getCompleteSelectors(selectorInfo),document:sourceDoc,lineStart:selectorInfo.ruleStartLine+lineOffset,lineEnd:selectorInfo.declListEndLine+lineOffset,selectorGroup:selectorInfo.selectorGroup})})}function _findMatchingRulesInCSSFiles(selector,resultSelectors){var result=new $.Deferred;function _loadFileAndScan(fullPath,selector){var oneFileResult=new $.Deferred;return DocumentManager.getDocumentForPath(fullPath).done(function(doc){var oneCSSFileMatches=_findAllMatchingSelectorsInText(doc.getText(),selector,doc.getLanguage().getMode());_addSelectorsToResults(resultSelectors,oneCSSFileMatches,doc,0),oneFileResult.resolve()}).fail(function(error){console.warn("Unable to read "+fullPath+" during CSS rule search:",error),oneFileResult.resolve()}),oneFileResult.promise()}return ProjectManager.getAllFiles(ProjectManager.getLanguageFilter(["css","less","scss"])).done(function(cssFiles){Async.doInParallel(cssFiles,function(fileInfo,number){return _loadFileAndScan(fileInfo.fullPath,selector)}).then(result.resolve,result.reject)}),result.promise()}function _findMatchingRulesInStyleBlocks(htmlDocument,selector,resultSelectors){var htmlEditor=EditorManager.getCurrentFullEditor(),styleBlocks;htmlEditor.document===htmlDocument?HTMLUtils.findStyleBlocks(htmlEditor).forEach(function(styleBlockInfo){var oneStyleBlockMatches=_findAllMatchingSelectorsInText(styleBlockInfo.text,selector);_addSelectorsToResults(resultSelectors,oneStyleBlockMatches,htmlDocument,styleBlockInfo.start.line)}):console.error("Cannot search for