public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets) { //AsmDudeToolsStatic.Output(string.Format(CultureInfo.CurrentCulture, "INFO: {0}:AugmentCompletionSession", this.ToString())); if (!Settings.Default.CodeCompletion_On) { return; } if (_disposed) { throw new ObjectDisposedException("AsmCompletionSource"); } try { DateTime time1 = DateTime.Now; ITextSnapshot snapshot = this._buffer.CurrentSnapshot; SnapshotPoint triggerPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot); if (triggerPoint == null) { return; } ITextSnapshotLine line = triggerPoint.GetContainingLine(); //1] check if current position is in a remark; if we are in a remark, no code completion if (AsmCompletionSource.isRemark(triggerPoint, line.Start)) { return; } //2] find the start of the current keyword SnapshotPoint start = triggerPoint; while ((start > line.Start) && !AsmTools.Tools.isSeparatorChar((start - 1).GetChar())) { start -= 1; } //3] get the word that is currently being typed var applicableTo = snapshot.CreateTrackingSpan(new SnapshotSpan(start, triggerPoint), SpanTrackingMode.EdgeInclusive); string partialKeyword = applicableTo.GetText(snapshot); bool useCapitals = AsmDudeToolsStatic.isAllUpper(partialKeyword); //4] get the previous keyword to narrow down the possible suggestions string previousKeyword = AsmCompletionSource.getPreviousKeyword(line.Start, start); IList <Completion> completions = null; if ((previousKeyword.Length == 0) || this.isLabel(previousKeyword)) { // no previous keyword exists. Do not suggest a register HashSet <TokenType> selected = new HashSet <TokenType> { TokenType.Directive, TokenType.Jump, TokenType.Misc, TokenType.Mnemonic /*, TokenType.Register*/ }; completions = this.selectedCompletions(useCapitals, selected); } else if (this.isJump(previousKeyword)) { // previous keyword is jump (or call) mnemonic. Suggest "SHORT" or a label completions = this.labelCompletions(); completions.Add(new Completion("SHORT", (useCapitals) ? "SHORT" : "short", null, this._icons[TokenType.Misc], "")); } else if (previousKeyword.Equals("SHORT")) { // previous keyword is SHORT. Suggest a label completions = this.labelCompletions(); } else if (this.isRegister(previousKeyword)) { // if the previous keyword is a register, suggest registers (of equal size), no opcodes and no directives HashSet <TokenType> selected = new HashSet <TokenType> { /*TokenType.Directive, TokenType.Jump,*/ TokenType.Misc, /*TokenType.Mnemonic,*/ TokenType.Register }; completions = this.selectedCompletions(useCapitals, selected); } else if (this.isMnemonic(previousKeyword)) { // if previous keyword is a mnemonic (no jump). Do not suggest a Mnemonic or directive HashSet <TokenType> selected = new HashSet <TokenType> { /*TokenType.Directive, TokenType.Jump,*/ TokenType.Misc, /*TokenType.Mnemonic,*/ TokenType.Register }; completions = this.selectedCompletions(useCapitals, selected); } else { HashSet <TokenType> selected = new HashSet <TokenType> { TokenType.Directive, TokenType.Jump, TokenType.Misc, TokenType.Mnemonic, TokenType.Register }; completions = this.selectedCompletions(useCapitals, selected); } completionSets.Add(new CompletionSet("Tokens", "Tokens", applicableTo, completions, Enumerable.Empty <Completion>())); double elapsedSec = (double)(DateTime.Now.Ticks - time1.Ticks) / 10000000; if (elapsedSec > AsmDudePackage.slowWarningThresholdSec) { AsmDudeToolsStatic.Output(string.Format("WARNING: SLOW: took {0:F3} seconds to prepare code completion for previous keyword \"{1}\" and current keyword \"{2}\".", elapsedSec, previousKeyword, partialKeyword, elapsedSec)); } } catch (Exception e) { AsmDudeToolsStatic.Output(string.Format("ERROR: {0}:AugmentCompletionSession; e={1}", this.ToString(), e.ToString())); } }
public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets) { //AsmDudeToolsStatic.Output(string.Format("INFO: {0}:AugmentCompletionSession", this.ToString())); if (_disposed) { return; } if (!Settings.Default.CodeCompletion_On) { return; } try { DateTime time1 = DateTime.Now; ITextSnapshot snapshot = this._buffer.CurrentSnapshot; SnapshotPoint triggerPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot); if (triggerPoint == null) { return; } ITextSnapshotLine line = triggerPoint.GetContainingLine(); //1] check if current position is in a remark; if we are in a remark, no code completion #region if (triggerPoint.Position > 1) { char currentTypedChar = (triggerPoint - 1).GetChar(); //AsmDudeToolsStatic.Output("INFO: CodeCompletionSource:AugmentCompletionSession: current char = "+ currentTypedChar); if (!currentTypedChar.Equals('#')) //TODO UGLY since the user can configure this starting character { int pos = triggerPoint.Position - line.Start; if (AsmSourceTools.isInRemark(pos, line.GetText())) { //AsmDudeToolsStatic.Output("INFO: CodeCompletionSource:AugmentCompletionSession: currently in a remark section"); return; } else { // AsmDudeToolsStatic.Output("INFO: CodeCompletionSource:AugmentCompletionSession: not in a remark section"); } } } #endregion //2] find the start of the current keyword #region SnapshotPoint start = triggerPoint; while ((start > line.Start) && !AsmTools.AsmSourceTools.isSeparatorChar((start - 1).GetChar())) { start -= 1; } #endregion //3] get the word that is currently being typed #region ITrackingSpan applicableTo = snapshot.CreateTrackingSpan(new SnapshotSpan(start, triggerPoint), SpanTrackingMode.EdgeInclusive); string partialKeyword = applicableTo.GetText(snapshot); bool useCapitals = AsmDudeToolsStatic.isAllUpper(partialKeyword); SortedSet <Completion> completions = null; string lineStr = line.GetText(); var t = AsmSourceTools.parseLine(lineStr); Mnemonic mnemonic = t.Item2; if (mnemonic == Mnemonic.UNKNOWN) { ISet <AsmTokenType> selected = new HashSet <AsmTokenType> { AsmTokenType.Directive, AsmTokenType.Jump, AsmTokenType.Misc, AsmTokenType.Mnemonic /*, AsmTokenType.Register */ }; completions = this.selectedCompletions(useCapitals, selected); } else // the current line contains a mnemonic { string previousKeyword = AsmDudeToolsStatic.getPreviousKeyword(line.Start, start); //AsmDudeToolsStatic.Output("INFO: AsmCompletionSource:AugmentCompletionSession; mnemonic=" + mnemonic+ "; previousKeyword="+ previousKeyword); if (AsmSourceTools.isJump(AsmSourceTools.parseMnemonic(previousKeyword))) { //AsmDudeToolsStatic.Output("INFO: AsmCompletionSource:AugmentCompletionSession; previous keyword is a jump mnemonic"); // previous keyword is jump (or call) mnemonic. Suggest "SHORT" or a label completions = this.labelCompletions(); completions.Add(new Completion("SHORT", (useCapitals) ? "SHORT" : "short", null, this._icons[AsmTokenType.Misc], "")); completions.Add(new Completion("NEAR", (useCapitals) ? "NEAR" : "near", null, this._icons[AsmTokenType.Misc], "")); } else if (previousKeyword.Equals("SHORT") || previousKeyword.Equals("NEAR")) { // previous keyword is SHORT. Suggest a label completions = this.labelCompletions(); } else { IList <Operand> operands = AsmSourceTools.makeOperands(t.Item3); ISet <AsmSignatureEnum> allowed = new HashSet <AsmSignatureEnum>(); int commaCount = AsmSignature.countCommas(lineStr); IList <AsmSignatureElement> allSignatures = this._asmDudeTools.mnemonicStore.getSignatures(mnemonic); ISet <Arch> selectedArchitectures = AsmDudeToolsStatic.getArchSwithedOn(); foreach (AsmSignatureElement se in AsmSignatureHelpSource.constrainSignatures(allSignatures, operands, selectedArchitectures)) { if (commaCount < se.operands.Count) { foreach (AsmSignatureEnum s in se.operands[commaCount]) { allowed.Add(s); } } } completions = this.mnemonicOperandCompletions(useCapitals, allowed); } } //AsmDudeToolsStatic.Output("INFO: AsmCompletionSource:AugmentCompletionSession; nCompletions=" + completions.Count); #endregion completionSets.Add(new CompletionSet("Tokens", "Tokens", applicableTo, completions, Enumerable.Empty <Completion>())); AsmDudeToolsStatic.printSpeedWarning(time1, "Code Completion"); } catch (Exception e) { AsmDudeToolsStatic.Output(string.Format("ERROR: {0}:AugmentCompletionSession; e={1}", this.ToString(), e.ToString())); } }