private void UpdateWordAdornments(object threadContext) { if (!Enabled) { return; } Enabled = false; SnapshotPoint currentRequest = RequestedPoint; List <SnapshotSpan> wordSpans = new List <SnapshotSpan>(); // Find all words in the buffer like the one the caret is on TextExtent word = TextStructureNavigator.GetExtentOfWord(currentRequest); bool foundWord = true; // If we've selected something not worth highlighting, we might have // missed a "word" by a little bit if (!WordExtentIsValid(currentRequest, word)) { // Before we retry, make sure it is worthwhile if (word.Span.Start != currentRequest || currentRequest == currentRequest.GetContainingLine().Start || char.IsWhiteSpace((currentRequest - 1).GetChar())) { foundWord = false; } else { // Try again, one character previous. If the caret is at the end of a word, then // this will pick up the word we are at the end of. word = TextStructureNavigator.GetExtentOfWord(currentRequest - 1); // If we still aren't valid the second time around, we're done if (!WordExtentIsValid(currentRequest, word)) { foundWord = false; } } } if (!foundWord) { // If we couldn't find a word, just clear out the existing markers SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); return; } SnapshotSpan currentWord = word.Span; // If this is the same word we currently have, we're done (e.g. caret moved within a word). if (CurrentWord.HasValue && currentWord == CurrentWord) { return; } /* Find spans using simple text search.... * FindData findData = new FindData(currentWord.GetText(), currentWord.Snapshot); * findData.FindOptions = FindOptions.WholeWord | FindOptions.MatchCase; * wordSpans.AddRange(TextSearchService.FindAll(findData)); */ // Verify current word is a grammar symbol. // Now, check for valid classification type. string classification = null; ClassificationSpan[] c1 = _aggregator.GetClassificationSpans(currentWord).ToArray(); foreach (ClassificationSpan cl in c1) { classification = cl.ClassificationType.Classification.ToLower(); if (classification == AntlrVSIX.Constants.ClassificationNameTerminal) { break; } else if (classification == AntlrVSIX.Constants.ClassificationNameNonterminal) { break; } } if (classification == null) { return; } SnapshotSpan span = currentWord; ITextView view = this.View; // First, find out what this view is, and what the file is. ITextBuffer buffer = view.TextBuffer; ITextDocument doc = buffer.GetTextDocument(); string path = doc.FilePath; List <IToken> where = new List <IToken>(); List <ParserDetails> where_details = new List <ParserDetails>(); IToken token = null; foreach (var kvp in ParserDetails._per_file_parser_details) { string file_name = kvp.Key; ParserDetails details = kvp.Value; if (classification == AntlrVSIX.Constants.ClassificationNameNonterminal) { var it = details._ant_nonterminals.Where( (t) => t.Text == span.GetText()); where.AddRange(it); foreach (var i in it) { where_details.Add(details); } } else if (classification == AntlrVSIX.Constants.ClassificationNameTerminal) { var it = details._ant_terminals.Where( (t) => t.Text == span.GetText()); where.AddRange(it); foreach (var i in it) { where_details.Add(details); } } else if (classification == AntlrVSIX.Constants.ClassificationNameLiteral) { var it = details._ant_literals.Where( (t) => t.Text == span.GetText()); where.AddRange(it); foreach (var i in it) { where_details.Add(details); } } } if (!where.Any()) { return; } // Populate the Antlr find results model/window with file/line/col info // for each occurrence. var results = new List <Entry>(); for (int i = 0; i < where.Count; ++i) { IToken x = where[i]; ParserDetails y = where_details[i]; var w = new Entry() { FileName = y.full_file_name, LineNumber = x.Line, ColumnNumber = x.Column, Token = x }; results.Add(w); } // Now, for all entries which are in this buffer, highlight. //wordSpans.Add(currentWord); for (int i = 0; i < results.Count; ++i) { var w = results[i]; if (w.FileName == path) { // Create new span in the appropriate view. ITextSnapshot cc = buffer.CurrentSnapshot; SnapshotSpan ss = new SnapshotSpan(cc, w.Token.StartIndex, 1 + w.Token.StopIndex - w.Token.StartIndex); SnapshotPoint sp = ss.Start; wordSpans.Add(ss); } } // If we are still up-to-date (another change hasn't happened yet), do a real update if (currentRequest == RequestedPoint) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(wordSpans), currentWord); } // Call up the rename dialog box. In another thread because // of "The calling thread must be STA, because many UI components require this." // error. Application.Current.Dispatcher.Invoke((Action) delegate { RenameDialogBox inputDialog = new RenameDialogBox(currentWord.GetText()); if (inputDialog.ShowDialog() == true) { results.Reverse(); var new_name = inputDialog.Answer; // Replace all occurrences of symbol, working backwards. foreach (Entry e in results) { string file_name = e.FileName; var pd = ParserDetails._per_file_parser_details[file_name]; IVsTextView vstv = IVsTextViewExtensions.GetIVsTextView(file_name); IWpfTextView wpftv = vstv.GetIWpfTextView(); if (wpftv == null) { // File has not been opened before! Open file in editor. IVsTextViewExtensions.ShowFrame(file_name); vstv = IVsTextViewExtensions.GetIVsTextView(file_name); wpftv = vstv.GetIWpfTextView(); } ITextBuffer tb = wpftv.TextBuffer; ITextSnapshot cc = tb.CurrentSnapshot; SnapshotSpan ss = new SnapshotSpan(cc, e.Token.StartIndex, 1 + e.Token.StopIndex - e.Token.StartIndex); SnapshotPoint sp = ss.Start; tb.Replace(ss, new_name); } // Reparse everything. foreach (string f in results.Select((e) => e.FileName).Distinct()) { ParserDetails foo = new ParserDetails(); ParserDetails._per_file_parser_details[f] = foo; IVsTextView vstv = IVsTextViewExtensions.GetIVsTextView(f); IWpfTextView wpftv = vstv.GetIWpfTextView(); if (wpftv == null) { continue; } ITextBuffer tb = wpftv.TextBuffer; foo.Parse(tb.GetBufferText(), f); } } }); }
private void RenameCallback(object sender, EventArgs e) { try { // Highlight the symbol, reposition it to the beginning of it. // Every character changes all occurrences of the symbol. SnapshotSpan span = AntlrLanguagePackage.Instance.Span; int curLoc = span.Start.Position; var buf = span.Snapshot.TextBuffer; var file_name = buf.GetFFN().Result; if (file_name == null) { return; } var document = Workspaces.Workspace.Instance.FindDocument(file_name); var ref_pd = ParserDetailsFactory.Create(document); if (ref_pd == null) { return; } var sym = LanguageServer.Module.GetDocumentSymbol(curLoc, document); if (sym == null) { return; } var locations = LanguageServer.Module.FindRefsAndDefs(curLoc, document); List <SnapshotSpan> wordSpans = new List <SnapshotSpan>(); var results = new List <Entry>(); foreach (var loc in locations) { if (global::Options.POptions.GetBoolean("RestrictedDirectory")) { string p1 = System.IO.Path.GetDirectoryName(file_name); string p2 = System.IO.Path.GetDirectoryName(loc.Uri.FullPath); if (p1 != p2) { continue; } } var w = new Entry() { FileName = loc.Uri.FullPath, Start = loc.Range.Start.Value, End = loc.Range.End.Value }; results.Add(w); } // Call up the rename dialog box. In another thread because // of "The calling thread must be STA, because many UI components require this." // error. Application.Current.Dispatcher.Invoke((Action) delegate { RenameDialogBox inputDialog = new RenameDialogBox(sym.name); if (inputDialog.ShowDialog() == true) { var new_name = inputDialog.Answer; var files = results.Select(r => r.FileName).OrderBy(q => q).Distinct(); foreach (var f in files) { var per_file_results = results.Where(r => r.FileName == f); per_file_results.Reverse(); var fitem = Workspaces.Workspace.Instance.FindDocument(f); var pd = ParserDetailsFactory.Create(fitem); IVsTextView vstv2 = IVsTextViewExtensions.FindTextViewFor(f); if (vstv2 == null) { // File has not been opened before! Open file in editor. IVsTextViewExtensions.ShowFrame(f); vstv2 = IVsTextViewExtensions.FindTextViewFor(f); } IWpfTextView wpftv2 = vstv2.GetIWpfTextView(); ITextBuffer tb = wpftv2.TextBuffer; using (var edit = tb.CreateEdit()) { ITextSnapshot cc2 = tb.CurrentSnapshot; foreach (var e2 in per_file_results) { SnapshotSpan ss2 = new SnapshotSpan(cc2, e2.Start, 1 + e2.End - e2.Start); SnapshotPoint sp2 = ss2.Start; edit.Replace(ss2, new_name); } edit.Apply(); } } } }); //AntlrVSIX.Package.Menus.ResetMenus(); } catch (Exception exception) { Logger.Log.Notify(exception.StackTrace); } }