/// <summary> /// Search the given span for any instances of classified tags /// </summary> public IEnumerable <ITagSpan <ClassificationTag> > GetTags(NormalizedSnapshotSpanCollection spans) { if (Settings.Default.SyntaxHighlighting_On) { if (spans.Count == 0) { //there is no content in the buffer yield break; } DateTime time1 = DateTime.Now; foreach (IMappingTagSpan <AsmTokenTag> tagSpan in _aggregator.GetTags(spans)) { NormalizedSnapshotSpanCollection tagSpans = tagSpan.Span.GetSpans(spans[0].Snapshot); switch (tagSpan.Tag.type) { case AsmTokenType.Mnemonic: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _mnemonic)); break; case AsmTokenType.Register: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _register)); break; case AsmTokenType.Remark: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _remark)); break; case AsmTokenType.Directive: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _directive)); break; case AsmTokenType.Constant: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _constant)); break; case AsmTokenType.Jump: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _jump)); break; case AsmTokenType.Label: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _label)); break; case AsmTokenType.LabelDef: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _labelDef)); break; case AsmTokenType.Misc: yield return(new TagSpan <ClassificationTag>(tagSpans[0], _misc)); break; default: break; } } AsmDudeToolsStatic.printSpeedWarning(time1, "Asm Classifier"); } }
public IEnumerable <ITagSpan <AsmTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans) { DateTime time1 = DateTime.Now; if (spans.Count == 0) { //there is no content in the buffer yield break; } foreach (SnapshotSpan curSpan in spans) { ITextSnapshotLine containingLine = curSpan.Start.GetContainingLine(); string line = containingLine.GetText().ToUpper(); IList <Tuple <int, int, bool> > pos = AsmSourceTools.splitIntoKeywordPos(line); int offset = containingLine.Start.Position; int nKeywords = pos.Count; for (int k = 0; k < nKeywords; k++) { if (pos[k].Item3) { SnapshotSpan label = newSpan(pos[k], offset, curSpan); string labelString = label.GetText(); //AsmDudeToolsStatic.Output(string.Format("INFO: found label {0}", labelString)); if (labelString.StartsWith(".")) { // TODO: special NASM local labels, for the moment, ignore them. } else { yield return(new TagSpan <AsmTokenTag>(label, this._labelDef)); } continue; } string asmToken = keyword(pos[k], line); if (AsmSourceTools.isRemarkChar(asmToken[0])) { yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._remark)); continue; } AsmTokenType keywordType = this._asmDudeTools.getTokenType(asmToken); switch (keywordType) { case AsmTokenType.Jump: #region Jump yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._jump)); k++; if (k == nKeywords) { break; } string asmToken2 = keyword(pos[k], line); if (!asmToken2[0].Equals('.')) { switch (asmToken2) { case "WORD": case "DWORD": case "QWORD": case "SHORT": case "NEAR": yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._misc)); k++; if (k == nKeywords) { break; } string asmToken3 = keyword(pos[k], line); if (!asmToken3[0].Equals('.')) { switch (asmToken3) { case "PTR": yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._misc)); break; default: yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._label)); break; } } break; default: if (RegisterTools.isRegister(asmToken2)) { yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._register)); } else { yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._label)); } break; } } break; #endregion Jump case AsmTokenType.UNKNOWN: // asmToken is not a known keyword, check if it is numerical #region UNKNOWN if (AsmTools.AsmSourceTools.isConstant(asmToken)) { yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._constant)); } else if (asmToken.StartsWith("\"") && asmToken.EndsWith("\"")) { yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._constant)); } else { bool isUnknown = true; // do one word lookahead; see whether we can understand the current unknown word if ((k + 1) < nKeywords) { k++; string nextKeyword = keyword(pos[k], line); switch (nextKeyword) { case "LABEL": yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k - 1], offset, curSpan), this._labelDef)); yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._directive)); isUnknown = false; break; default: k--; break; } } // do one word look back; see whether we can understand the current unknown word if (k > 0) { string previousKeyword = keyword(pos[k - 1], line); switch (previousKeyword) { case "ALIAS": yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._labelDef)); isUnknown = false; break; default: break; } } if (isUnknown) { yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._UNKNOWN)); } } break; #endregion UNKNOWN case AsmTokenType.Directive: #region Directive switch (this._asmDudeTools.getAssembler(asmToken)) { case AssemblerEnum.NASM: case AssemblerEnum.UNKNOWN: yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), this._directive)); break; default: break; } break; #endregion Directive default: yield return(new TagSpan <AsmTokenTag>(newSpan(pos[k], offset, curSpan), new AsmTokenTag(keywordType))); break; } } } AsmDudeToolsStatic.printSpeedWarning(time1, "NasmTokenTagger"); }
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())); } }