diff --git a/CodeiumVS/CodeLens/CodeLensTag.cs b/CodeiumVS/CodeLens/CodeLensTag.cs
deleted file mode 100644
index 2fabfdd..0000000
--- a/CodeiumVS/CodeLens/CodeLensTag.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using Microsoft.VisualStudio.Text;
-using Microsoft.VisualStudio.Text.Tagging;
-
-namespace CodeiumVS
-{
-
- // the SpaceNegotiatingAdornmentTag is used to tell the editor to create an empty space
- // they work like a more complicated version of
from html
- internal class CodeLensTag : SpaceNegotiatingAdornmentTag
- {
- public CodeLensTag(double width, double topSpace, double baseline, double textHeight,
- double bottomSpace, PositionAffinity affinity, object identityTag,
- object providerTag)
- : base(width, topSpace, baseline, textHeight, bottomSpace, affinity, identityTag,
- providerTag)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/CodeiumVS/CodeLens/CodeLensTagger.cs b/CodeiumVS/CodeLens/CodeLensTagger.cs
deleted file mode 100644
index 1537ed3..0000000
--- a/CodeiumVS/CodeLens/CodeLensTagger.cs
+++ /dev/null
@@ -1,647 +0,0 @@
-using System.Collections.Generic;
-using System.Windows.Controls;
-using System.Windows.Media;
-using System.Windows.Documents;
-using System.Diagnostics;
-using Microsoft.VisualStudio.Text;
-using Microsoft.VisualStudio.Text.Editor;
-using Microsoft.VisualStudio.Text.Tagging;
-using System.Windows.Media.TextFormatting;
-using Microsoft.VisualStudio.Utilities;
-using System.ComponentModel.Composition;
-using Microsoft.VisualStudio.Text.Projection;
-using CodeiumVS.Languages;
-using System.IO;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Input;
-using CodeiumVS.Packets;
-using CodeiumVS.Utilities;
-using System.Windows.Shapes;
-using System;
-using WebSocketSharp;
-using System.Windows.Forms;
-
-namespace CodeiumVS
-{
-
- internal sealed class CodeLensTagger : ITagger, IDisposable
- {
-
- /// used to set the colour of the grey text
- private Brush greyBrush;
-
- /// contains the editor text and OnChange triggers on any text changes
- ITextBuffer buffer;
-
- /// current editor display, immutable data
- ITextSnapshot snapshot;
-
- /// the editor display object
- IWpfTextView view;
-
- /// contains the grey text
- private IAdornmentLayer adornmentLayer;
-
- private ITextDocument _document;
- private LangInfo _language;
-
- private CancellationTokenSource? _requestTokenSource;
- private CancellationTokenSource currentCancellTokenSource = null;
- private CancellationToken currentCancellToken;
-
- List _functions;
- List _classes;
- List originalSpans = new List();
- List panels = new List();
- private double lastViewPortTop = 0;
-
- public CodeLensTagger(IWpfTextView view, ITextBuffer buffer, ITextDocument document)
- {
- this.buffer = buffer;
- this.snapshot = buffer.CurrentSnapshot;
- this.view = view;
- this.adornmentLayer = view.GetAdornmentLayer("CodeiumCodeLensAdornmentLayer");
- _document = document;
- this.greyBrush = new SolidColorBrush(Colors.Gray);
-
- RefreshLanguage();
-
- view.TextBuffer.Changed += BufferChanged;
- this.view.LayoutChanged += this.OnSizeChanged;
-
- if (_document != null)
- {
- _document.FileActionOccurred += OnFileActionOccurred;
- _document.TextBuffer.ContentTypeChanged += OnContentTypeChanged;
- }
- Task.Run(() => Update());
- }
-
- private void OnContentTypeChanged(object sender, ContentTypeChangedEventArgs e)
- {
- RefreshLanguage();
- }
-
- private void OnFileActionOccurred(object sender, TextDocumentFileActionEventArgs e)
- {
- RefreshLanguage();
- }
-
- private void RefreshLanguage()
- {
- if (_document != null)
- {
- _language = Mapper.GetLanguage(_document.TextBuffer.ContentType,
- System.IO.Path.GetExtension(_document.FilePath)?.Trim('.'));
- }
- }
-
- // This an iterator that is used to iterate through all of the test tags
- // tags are like html tags they mark places in the view to modify how those sections look
- // Testtag is a tag that tells the editor to add empty space
- public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans)
- {
- ITextSnapshot currentSnapshot;
- double height, lineHeight;
- try
- {
- SnapshotSpan entire = new SnapshotSpan(spans[0].Start, spans[spans.Count - 1].End)
- .TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive);
- currentSnapshot = spans[0].Snapshot;
-
- height = view.LineHeight;
-
- lineHeight = view.LineHeight;
-
- }
- catch (Exception e)
- {
- yield break;
- }
-
- int index = 0;
- if (_functions != null)
- {
- foreach (FunctionInfo function in _functions)
- {
- int lineN = function.DefinitionLine;
- SnapshotSpan line;
- SnapshotSpan span;
-
- try
- {
- line = currentSnapshot.GetLineFromLineNumber(lineN).Extent;
- span = new SnapshotSpan(line.Start, line.Start);
- }
- catch (ArgumentOutOfRangeException e)
- {
- yield break;
- }
-
- yield return new TagSpan(
- span,
- new CodeLensTag(
- 0, height, 0, 0, 0, PositionAffinity.Predecessor, panels[index], this));
- index++;
- }
- }
-
- if (_classes != null)
- {
- foreach (ClassInfo c in _classes)
- {
- int lineN = c.StartLine;
- SnapshotSpan line;
- SnapshotSpan span;
-
- try
- {
- line = currentSnapshot.GetLineFromLineNumber(lineN).Extent;
- span = new SnapshotSpan(line.Start, line.Start);
- }
- catch (ArgumentOutOfRangeException e)
- {
- yield break;
- }
-
- yield return new TagSpan(
- span,
- new CodeLensTag(
- 0, height, 0, lineHeight, 0, PositionAffinity.Predecessor, panels[index], this));
- }
- }
- }
-
- public event EventHandler TagsChanged;
-
- // triggers when the editor text buffer changes
- void BufferChanged(object sender, TextContentChangedEventArgs e)
- {
- // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll
- // eventually get another change event).
- if (e.After != buffer.CurrentSnapshot) return;
-
- Task.Run(() => Update());
- }
-
- TextBlock CreateTextBox(int i, bool needsGoDoc)
- {
- TextBlock textBlock = new TextBlock();
-
- var RefactorRun = new Run("Refactor") { Foreground = greyBrush };
- RefactorRun.MouseUp += (object sender, MouseButtonEventArgs e) => ClickRefactor(i);
- var ExplainRun = new Run("Explain") { Foreground = greyBrush };
- ExplainRun.MouseUp += (object sender, MouseButtonEventArgs e) => ClickExplain(i);
- var DocRun = new Run("DocString") { Foreground = greyBrush };
- DocRun.MouseUp += (object sender, MouseButtonEventArgs e) => ClickDoc(i);
-
- textBlock.Inlines.Add(new Run("Codeium: ") { Foreground = greyBrush });
- textBlock.Inlines.Add(RefactorRun);
- textBlock.Inlines.Add(new Run(" | ") { Foreground = greyBrush });
- textBlock.Inlines.Add(ExplainRun);
-
- if (needsGoDoc)
- {
- textBlock.Inlines.Add(new Run(" | ") { Foreground = greyBrush });
- textBlock.Inlines.Add(DocRun);
- }
-
- return textBlock;
- }
-
- FunctionInfo GetFunN(int n)
- {
- var funcLength = _functions == null ? 0 : _functions.Count;
-
- if (n >= funcLength)
- {
- return null;
- }
- else
- {
- return _functions[n];
- }
- }
-
- ClassInfo GetClassN(int n)
- {
- var funcLength = _functions == null ? 0 : _functions.Count;
-
- if (n >= funcLength)
- {
- n -= funcLength;
- if (_classes.Count <= n) return null;
- return _classes[n];
- }
- else
- {
- return null;
- }
- }
-
- async void ClickRefactor(int i)
- {
- try
- {
- LanguageServerController controller =
- CodeiumVSPackage.Instance.LanguageServer.Controller;
-
- FunctionInfo functionInfo = GetFunN(i);
- ClassInfo classInfo;
- int lineN;
- if (functionInfo == null)
- {
- classInfo = GetClassN(i);
- lineN = classInfo.StartLine;
- }
- else
- {
- lineN = functionInfo.DefinitionLine;
- }
- var span = originalSpans[i].TranslateTo(view.TextSnapshot, SpanTrackingMode.EdgePositive);
- ITextSnapshotLine snapshotLine = span.Start.GetContainingLine();
- var start = view.TextViewLines.GetCharacterBounds(snapshotLine.Start);
-
- // highlight the selected codeblock
- TextHighlighter? highlighter = TextHighlighter.GetInstance(view);
- highlighter?.AddHighlight(snapshotLine.Extent);
- var dialog = RefactorCodeDialogWindow.GetOrCreate();
- var prompt =
- await dialog.ShowAndGetPromptAsync(_language, start.Left - view.ViewportLeft, start.Top - view.ViewportTop);
-
- highlighter?.ClearAll();
-
- // user did not select any of the prompt
- if (prompt == null) return;
- if (functionInfo != null)
- {
- controller.RefactorFunctionAsync(
- prompt, _document.FilePath, functionInfo);
- }
- else
- {
- classInfo = GetClassN(i);
- if (classInfo == null) return;
- CodeBlockInfo codeBlockInfo = ClassToCodeBlock(classInfo);
-
- controller.ExplainCodeBlockAsync(_document.FilePath, _language.Type, codeBlockInfo);
- }
-
- }
- catch (Exception e)
- {
-
- }
- }
-
- void ClickExplain(int i)
- {
- LanguageServerController controller =
- CodeiumVSPackage.Instance.LanguageServer.Controller;
-
- FunctionInfo functionInfo = GetFunN(i);
- if (functionInfo != null)
- {
- controller.ExplainFunctionAsync(_document.FilePath, functionInfo);
- }
- else
- {
- ClassInfo classInfo = GetClassN(i);
- if (classInfo == null) return;
- CodeBlockInfo codeBlockInfo = ClassToCodeBlock(classInfo);
- controller.ExplainCodeBlockAsync(
- _document.FilePath, _language.Type, codeBlockInfo);
- }
- }
-
- CodeBlockInfo ClassToCodeBlock(ClassInfo classInfo)
- {
- CodeBlockInfo codeBlockInfo = new CodeBlockInfo();
- codeBlockInfo.start_line = classInfo.StartLine;
- codeBlockInfo.end_line = classInfo.EndLine;
- codeBlockInfo.start_col = classInfo.StartCol;
- codeBlockInfo.end_col = classInfo.EndCol;
- return codeBlockInfo;
- }
-
- void ClickDoc(int i)
- {
- LanguageServerController controller =
- CodeiumVSPackage.Instance.LanguageServer.Controller;
-
- FunctionInfo functionInfo = GetFunN(i);
-
- if (functionInfo != null)
- {
- controller.GenerateFunctionDocstringAsync(_document.FilePath, functionInfo);
- }
- }
-
- private void UpdatePanel(StackPanel panel, int index, bool needsGoDoc)
- {
- panel.Children.Clear();
- panel.Children.Add(CreateTextBox(index, needsGoDoc));
- }
- private void AddPanel(bool needsGoDoc)
- {
- CreateStackPanel(needsGoDoc);
- }
-
- private void RemovePanel(List panels)
- {
- panels.RemoveAt(panels.Count - 1);
- }
-
- void CreateStackPanel(bool needsGoDoc)
- {
- var stackPanel = new StackPanel();
- stackPanel.Children.Add(CreateTextBox(panels.Count, needsGoDoc));
- panels.Add(stackPanel);
- }
-
- private void SetPosition(SnapshotSpan orginalLine, StackPanel panel)
- {
- try
- {
-
- var snapshotSpan = orginalLine.TranslateTo(view.TextSnapshot, SpanTrackingMode.EdgeExclusive);
- ITextSnapshotLine snapshotLine = snapshotSpan.Start.GetContainingLine();
- if (view.TextViewLines.FirstVisibleLine.Start < snapshotLine.Start &&
- view.TextViewLines.LastVisibleLine.End >= snapshotLine.Start)
- {
- var text = snapshotLine.GetText();
- int emptySpaceLength = text.Length - text.TrimStart().Length;
-
- var start = view.TextViewLines.GetCharacterBounds(snapshotLine.Start.Add(emptySpaceLength));
-
- if (panel.Children.Count > 0)
- {
- var span = snapshotLine.Extent;
- // Place the image in the top left hand corner of the line
- Canvas.SetLeft(panel, start.Left);
- Canvas.SetTop(element: panel, start.TextTop - view.LineHeight);
-
- // Add the image to the adornment layer and make it relative to the viewport
- this.adornmentLayer.AddAdornment(
- AdornmentPositioningBehavior.TextRelative, span, null, panel, null);
- }
- }
- }
- catch (Exception e) { Debug.Write(e); }
- }
-
- private void UpdateAdornments()
- {
- this.adornmentLayer.RemoveAllAdornments();
- int i = 0;
-
- if(originalSpans == null) return;
- if (_functions != null)
- {
- foreach (var function in _functions)
- {
- if (originalSpans.Count > i)
- {
- SetPosition(originalSpans[i], panels[i]);
- }
- i++;
- }
- }
-
- if (_classes != null)
- {
- foreach (var c in _classes)
- {
- if (originalSpans.Count > i)
- {
- SetPosition(originalSpans[i], panels[i]);
- }
- i++;
- }
- }
-
- }
-
- // Adds grey text to display
- private void OnSizeChanged(object sender, EventArgs e)
- {
- UpdateAdornments();
- if ( Math.Abs(lastViewPortTop - view.ViewportTop) > Double.Epsilon)
- {
- lastViewPortTop = view.ViewportTop;
- MarkDirty();
- }
- }
-
- // update multiline data
- public async Task Update()
- {
-
- while (CodeiumVSPackage.Instance == null || CodeiumVSPackage.Instance.LanguageServer == null)
- {
- await Task.Delay(100);
- }
-
- try
- {
- lastViewPortTop = view.ViewportTop;
-
- string text = _document.TextBuffer.CurrentSnapshot.GetText();
- SnapshotPoint? caretPoint = view.Caret.Position.Point.GetPoint(
- textBuffer => (!textBuffer.ContentType.IsOfType("projection")),
- PositionAffinity.Successor);
- if (!caretPoint.HasValue)
- {
- return false;
- }
-
- var caretPosition = caretPoint.Value.Position;
-
- int cursorPosition = _document.Encoding.IsSingleByte
- ? caretPosition
- : Utf16OffsetToUtf8Offset(text, caretPosition);
-
- if (cursorPosition > text.Length)
- {
- Debug.Print("Error Caret past text position");
- return false;
- }
-
- UpdateRequestTokenSource(new CancellationTokenSource());
- IList? functions =
- await CodeiumVSPackage.Instance.LanguageServer.GetFunctionsAsync(
- _document.FilePath,
- text,
- _language,
- cursorPosition,
- view.Options.GetOptionValue(DefaultOptions.NewLineCharacterOptionId),
- currentCancellTokenSource.Token);
-
- IList? classes = await CodeiumVSPackage.Instance.LanguageServer.GetClassInfosAsync(
- _document.FilePath,
- text,
- _language,
- cursorPosition,
- view.Options.GetOptionValue(DefaultOptions.NewLineCharacterOptionId),
- currentCancellTokenSource.Token);
-
- await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
-
- _functions = (List)functions;
- _classes = (List)classes;
-
- originalSpans.Clear();
- int index = 0;
- foreach (FunctionInfo function in _functions)
- {
- if (panels.Count > index)
- {
- var panel = panels[index];
- var needsGoDoc = function.Docstring.IsNullOrEmpty();
- var childrenCount = (panel.Children[0] as TextBlock).Inlines.Count;
- if ((needsGoDoc && childrenCount < 5) || (!needsGoDoc && childrenCount > 5))
- {
- UpdatePanel(panel, index, needsGoDoc);
- }
- }
- originalSpans.Add(view.TextSnapshot.GetLineFromLineNumber(function.DefinitionLine).Extent);
- index++;
- }
-
- foreach (ClassInfo c in classes)
- {
- if (panels.Count > index)
- {
- var panel = panels[index];
- if((panel.Children[0] as TextBlock).Inlines.Count >= 5)
- {
- UpdatePanel(panel, index, false);
- }
- }
-
- originalSpans.Add(view.TextSnapshot.GetLineFromLineNumber(c.DefinitionLine).Extent);
- index++;
- }
-
- int panelDiff = (_functions.Count + _classes.Count) - panels.Count;
- if (panelDiff > 0)
- {
- for (int i = 0; i < panelDiff; i++)
- {
- FunctionInfo function = GetFunN(i);
- bool needsGoDoc = function != null && function.Docstring.IsNullOrEmpty();
- AddPanel(needsGoDoc);
- }
- }
- else if (panelDiff < 0)
- {
- for (int i = 0; i < panelDiff; i++)
- {
- RemovePanel(panels);
- }
- }
-
- UpdateAdornments();
- MarkDirty();
-
- return true;
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- private void UpdateRequestTokenSource(CancellationTokenSource newSource)
- {
- if (currentCancellTokenSource != null)
- {
- currentCancellTokenSource.Cancel();
- currentCancellTokenSource.Dispose();
- }
- currentCancellTokenSource = newSource;
- }
- public static int Utf16OffsetToUtf8Offset(string str, int utf16Offset)
- {
- return Encoding.UTF8.GetByteCount(str.ToCharArray(), 0, utf16Offset);
- }
-
- // triggers refresh of the screen
- void MarkDirty()
- {
- try
- {
- ITextSnapshot newSnapshot = buffer.CurrentSnapshot;
- this.snapshot = newSnapshot;
-
- if (view.TextViewLines == null) return;
- if (!view.TextViewLines.IsValid) return;
-
- var changeStart = view.TextViewLines.FirstVisibleLine.Start;
- var changeEnd = view.TextViewLines.LastVisibleLine.Start;
-
- var startLine = view.TextSnapshot.GetLineFromPosition(changeStart);
- var endLine = view.TextSnapshot.GetLineFromPosition(changeEnd);
-
- var span = new SnapshotSpan(startLine.Start, endLine.EndIncludingLineBreak)
- .TranslateTo(targetSnapshot: newSnapshot, SpanTrackingMode.EdgePositive);
-
- // lines we are marking dirty
- // currently all of them for simplicity
- if (this.TagsChanged != null) { TagsChanged(this, new SnapshotSpanEventArgs(span)); }
- }
- catch (Exception e) { Debug.Write(e); }
- }
-
- public void Dispose()
- {
- _document.FileActionOccurred -= OnFileActionOccurred;
- _document.TextBuffer.ContentTypeChanged -= OnContentTypeChanged;
- UpdateRequestTokenSource(null);
- }
-
- }
-
- [Export(typeof(IViewTaggerProvider))]
- [TagType(typeof(CodeLensTag))]
- [ContentType("text")]
- internal sealed class CodeLensProvider : IViewTaggerProvider
- {
-
- [Export(typeof(AdornmentLayerDefinition))]
- [Name("CodeiumCodeLensAdornmentLayer")]
- [Order(After = PredefinedAdornmentLayers.Caret)]
- private AdornmentLayerDefinition codeLensAdornmentLayer;
-
-#pragma warning restore 649, 169
-
- // document factory is used to get information about the current text document such as filepath,
- // language, etc.
- [Import]
- internal ITextDocumentFactoryService documentFactory = null;
-
- // create a single tagger for each buffer.
- // the MultilineGreyTextTagger displays the grey text in the editor.
- public ITagger CreateTagger(ITextView textView, ITextBuffer buffer)
- where T : ITag
- {
- var topBuffer = textView.BufferGraph.TopBuffer;
-
- var projectionBuffer = topBuffer as IProjectionBufferBase;
-
- ITextBuffer textBuffer =
- projectionBuffer != null ? projectionBuffer.SourceBuffers[0] : topBuffer;
- ITextDocument _document;
- documentFactory.TryGetTextDocument(textBuffer, out _document);
- if(_document == null) return null;
- Func> sc = delegate ()
- {
- return new CodeLensTagger((IWpfTextView)textView, buffer, _document) as ITagger;
- };
- return buffer.Properties.GetOrCreateSingletonProperty>(typeof(CodeLensTagger),
- sc);
- }
- }
-}
diff --git a/CodeiumVS/CodeLensConnection/CodeLensConnectionHandler.cs b/CodeiumVS/CodeLensConnection/CodeLensConnectionHandler.cs
new file mode 100644
index 0000000..c8b4d8d
--- /dev/null
+++ b/CodeiumVS/CodeLensConnection/CodeLensConnectionHandler.cs
@@ -0,0 +1,98 @@
+#nullable enable
+
+using System.Collections.Generic;
+using CodeiumVS.Packets;
+
+namespace CodeiumVS
+{
+ using System;
+ using System.Diagnostics;
+ using System.IO.Pipes;
+ using System.Linq;
+ using System.Threading.Tasks;
+
+ using StreamJsonRpc;
+
+ using CodeLensConnections = System.Collections.Concurrent.ConcurrentDictionary;
+ using CodeLensDetails = System.Collections.Concurrent.ConcurrentDictionary;
+
+ public class CodeLensConnectionHandler : IRemoteVisualStudio, IDisposable
+ {
+ private static readonly CodeLensConnections connections = new CodeLensConnections();
+ private static readonly CodeLensDetails detailsData = new CodeLensDetails();
+
+ private JsonRpc? rpc;
+ private Guid? dataPointId;
+
+ public static async Task AcceptCodeLensConnections()
+ {
+ try
+ {
+ while (true)
+ {
+ var stream = new NamedPipeServerStream(
+ PipeName.Get(Process.GetCurrentProcess().Id),
+ PipeDirection.InOut,
+ NamedPipeServerStream.MaxAllowedServerInstances,
+ PipeTransmissionMode.Byte,
+ PipeOptions.Asynchronous);
+ await stream.WaitForConnectionAsync().Caf();
+ _ = HandleConnection(stream);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw;
+ }
+
+ static async Task HandleConnection(NamedPipeServerStream stream)
+ {
+ try
+ {
+ var handler = new CodeLensConnectionHandler();
+ var rpc = JsonRpc.Attach(stream, handler);
+ handler.rpc = rpc;
+ await rpc.Completion;
+ handler.Dispose();
+ stream.Dispose();
+ }
+ catch (Exception ex)
+ {
+ CodeiumVSPackage.Instance.LogAsync("Handle Connection Error");
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ if (dataPointId.HasValue)
+ {
+ _ = connections.TryRemove(dataPointId.Value, out var _);
+ _ = detailsData.TryRemove(dataPointId.Value, out var _);
+ }
+ }
+
+ // Called from each CodeLensDataPoint via JSON RPC.
+ public void RegisterCodeLensDataPoint(Guid id)
+ {
+ dataPointId = id;
+ connections[id] = this;
+ }
+
+ public static void StoreDetailsData(Guid id, FunctionInfo closestFunction) => detailsData[id] = closestFunction;
+
+ public static FunctionInfo GetDetailsData(Guid id) => detailsData[id];
+
+ public static async Task RefreshCodeLensDataPoint(Guid id)
+ {
+ if (!connections.TryGetValue(id, out var conn))
+ throw new InvalidOperationException($"CodeLens data point {id} was not registered.");
+
+ Debug.Assert(conn.rpc != null);
+ await conn.rpc!.InvokeAsync(nameof(IRemoteCodeLens.Refresh)).Caf();
+ }
+
+ public static async Task RefreshAllCodeLensDataPoints()
+ => await Task.WhenAll(connections.Keys.Select(RefreshCodeLensDataPoint)).Caf();
+ }
+}
diff --git a/CodeiumVS/CodeLensConnection/CodeLensListener.cs b/CodeiumVS/CodeLensConnection/CodeLensListener.cs
new file mode 100644
index 0000000..c11ced7
--- /dev/null
+++ b/CodeiumVS/CodeLensConnection/CodeLensListener.cs
@@ -0,0 +1,101 @@
+#nullable enable
+
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.Language.CodeLens;
+using Microsoft.VisualStudio.Utilities;
+using CodeiumVS.Packets;
+using Microsoft.VisualStudio.ComponentModelHost;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using System.Windows.Shapes;
+using Microsoft.VisualStudio.Debugger.Interop;
+
+namespace CodeiumVS
+{
+
+ [Export(typeof(ICodeLensCallbackListener))]
+ [ContentType("C/C++")]
+ [ContentType("CSharp")]
+ [ContentType("Basic")]
+ [ContentType("vbscript")]
+ [ContentType("TypeScript")]
+ [ContentType("JavaScript")]
+ public class CodeLensListener : ICodeLensCallbackListener, ICodeLensListener
+ {
+
+ public int GetVisualStudioPid() => Process.GetCurrentProcess().Id;
+
+ FunctionInfo GetClosestFunction(IList? functions, int line)
+ {
+
+ FunctionInfo minFunction = null;
+ int minDistance = int.MaxValue;
+ foreach (var f in functions)
+ {
+ var distance = Math.Abs(f.DefinitionLine - line);
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ minFunction = f;
+ }
+ }
+
+ return minFunction;
+ }
+
+ public async Task LoadInstructions(
+ Guid dataPointId,
+ Guid projGuid,
+ string filePath,
+ int textStart,
+ int textLen,
+ CancellationToken ct)
+ {
+ try
+ {
+
+ ITextDocument _document;
+ TextViewListener.Instance.documentDictionary.TryGetValue(filePath.ToLower(), out _document);
+ var key = typeof(CodeiumCompletionHandler);
+ var props = _document.TextBuffer.Properties;
+ CodeiumCompletionHandler handler;
+ if (props.ContainsProperty(key))
+ {
+ handler = props.GetProperty(key);
+ }
+ else
+ {
+ handler = null;
+ return null;
+ }
+
+ IList? functions =
+ await CodeiumVSPackage.Instance.LanguageServer.GetFunctionsAsync(
+ _document.FilePath,
+ _document.TextBuffer.CurrentSnapshot.GetText(),
+ handler.GetLanguage(),
+ 0,
+ ct);
+
+ var line = new Span(textStart, textLen);
+ var snapshotLine = _document.TextBuffer.CurrentSnapshot.GetLineFromPosition(line.Start);
+ var lineN = snapshotLine.LineNumber;
+ FunctionInfo closestFunction = GetClosestFunction(functions, lineN);
+ CodeLensConnectionHandler.StoreDetailsData(dataPointId, closestFunction);
+
+ return closestFunction;
+ }
+ catch (Exception ex)
+ {
+ CodeiumVSPackage.Instance.LogAsync(ex.ToString());
+
+ return null;
+ }
+ }
+
+ }
+}
diff --git a/CodeiumVS/CodeiumVS.csproj b/CodeiumVS/CodeiumVS.csproj
index e73cce1..6c42aaa 100644
--- a/CodeiumVS/CodeiumVS.csproj
+++ b/CodeiumVS/CodeiumVS.csproj
@@ -67,8 +67,12 @@
preview
-
-
+
+
+
+
+
+
InlineDiffControl.xaml
diff --git a/CodeiumVS/CodeiumVSPackage.cs b/CodeiumVS/CodeiumVSPackage.cs
index 5c15651..0293b44 100644
--- a/CodeiumVS/CodeiumVSPackage.cs
+++ b/CodeiumVS/CodeiumVSPackage.cs
@@ -81,6 +81,18 @@ await VS.MessageBox.ShowErrorAsync(
"Codeium might not work correctly. Please check the output window for more details.");
}
+ try
+ {
+ await base.InitializeAsync(cancellationToken, progress);
+ await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
+ _ = CodeLensConnectionHandler.AcceptCodeLensConnections();
+ }
+ catch (Exception ex)
+ {
+ await LogAsync("Codeium Error" + ex);
+ throw;
+ }
+
await LanguageServer.InitializeAsync();
await LogAsync("Codeium Extension for Visual Studio");
}
diff --git a/CodeiumVS/Commands.cs b/CodeiumVS/Commands.cs
index 5b6d3d8..f3b3dc3 100644
--- a/CodeiumVS/Commands.cs
+++ b/CodeiumVS/Commands.cs
@@ -9,6 +9,11 @@
using CodeiumVS.Packets;
using CodeiumVS.Utilities;
using System.Windows.Forms;
+using System.Collections.Generic;
+using System.Windows.Shapes;
+using static System.Windows.Forms.LinkLabel;
+using System.Threading;
+using Microsoft.VisualStudio.Language.CodeLens;
namespace CodeiumVS.Commands;
@@ -343,6 +348,269 @@ await controller.RefactorCodeBlockAsync(
}
}
+internal class BaseCommandCodeLens : BaseCommand
+ where T : class, new()
+{
+ internal static long lastQuery = 0;
+
+ protected static DocumentView? docView;
+ protected static string text; // the selected text
+ protected static Languages.LangInfo languageInfo;
+ protected FunctionInfo functionInfo;
+ protected ClassInfo classInfo;
+ protected override void BeforeQueryStatus(EventArgs e)
+ {
+ // Derived menu commands will call this repeatedly upon openning
+ // so we only want to do it once, i can't find a better way to do it
+ long timeStamp = Stopwatch.GetTimestamp();
+ if (lastQuery != 0 && timeStamp - lastQuery < 500) return;
+ lastQuery = timeStamp;
+
+ ThreadHelper.JoinableTaskFactory.Run(async delegate {
+
+ // any interactions with the `IVsTextView` should be done on the main thread
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+
+ try
+ {
+ docView = await VS.Documents.GetActiveDocumentViewAsync();
+ text = docView.TextBuffer.CurrentSnapshot.GetText();
+ if (docView?.TextView == null) return false;
+ }
+ catch (Exception ex)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(
+ $"BaseCommandContextMenu: Failed to get the active document view; Exception: {ex}");
+ return false;
+ }
+
+ languageInfo = Languages.Mapper.GetLanguage(docView);
+ ITextSelection selection = docView.TextView.Selection;
+
+ return true;
+ });
+ }
+
+ protected async Task ResolveCodeBlock(int startLine)
+ {
+ CancellationTokenSource cts = new CancellationTokenSource();
+ IList? functions =
+ await CodeiumVSPackage.Instance.LanguageServer.GetFunctionsAsync(
+ docView.FilePath,
+ text,
+ languageInfo,
+ 0,
+ cts.Token);
+
+ IList? classes = await CodeiumVSPackage.Instance.LanguageServer.GetClassInfosAsync(
+ docView.FilePath,
+ text,
+ languageInfo,
+ 0,
+ docView.TextView.Options.GetOptionValue(DefaultOptions.NewLineCharacterOptionId),
+ cts.Token);
+
+ FunctionInfo minFunction = null;
+ int minDistance = int.MaxValue;
+ foreach (var f in functions)
+ {
+ var distance = Math.Abs(f.DefinitionLine - startLine);
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ functionInfo = f;
+ }
+ }
+
+ foreach (var c in classes)
+ {
+ var distance = Math.Abs(c.StartLine - startLine);
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ functionInfo = null;
+ classInfo = c;
+ }
+ }
+ return true;
+ }
+
+ protected CodeBlockInfo ClassToCodeBlock(ClassInfo c)
+ {
+ CodeBlockInfo codeBlockInfo = null;
+ try
+ {
+ var snapshotLineStart = docView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(c.StartLine);
+ var snapShotLineEnd = docView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(c.EndLine);
+
+ var start_position = snapshotLineStart.Start;
+ var end_position = snapShotLineEnd.End;
+
+ var start_line = snapshotLineStart.LineNumber + 1;
+ var end_line = snapShotLineEnd.LineNumber + 1;
+ var start_col = start_position - snapshotLineStart.Start.Position + 1;
+ var end_col = end_position - snapShotLineEnd.Start.Position + 1;
+
+ text = docView.TextBuffer.CurrentSnapshot.GetText(start_position,
+ end_position - start_position);
+
+ codeBlockInfo = new()
+ {
+ raw_source = text,
+ start_line = start_line,
+ end_line = end_line,
+ start_col = start_col,
+ end_col = end_col,
+ };
+ }
+ catch (Exception ex)
+ {
+ Task.Run(async () =>
+ {
+ return CodeiumVSPackage.Instance.LogAsync(ex.ToString());
+ });
+ }
+ return codeBlockInfo;
+ }
+
+}
+
+
+[Command(PackageIds.RefactorSelectionCodeBlock)]
+internal class CommandRefactorSelectionCodeBlock : BaseCommandCodeLens
+{
+ protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)
+ {
+
+ try
+ {
+ LanguageServerController controller =
+ (Package as CodeiumVSPackage).LanguageServer.Controller;
+
+ CodeLensDescriptorContext ctx = null;
+ ITextSnapshotLine snapshotLine;
+ int startPos;
+ if (e.InValue != null)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(e.InValue.ToString());
+ ctx = e.InValue as CodeLensDescriptorContext;
+ startPos = ctx.ApplicableSpan.Value.Start;
+ snapshotLine = docView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPos);
+ int startLine = snapshotLine.LineNumber;
+ TextBounds selectionLine = docView.TextView.TextViewLines.GetCharacterBounds(snapshotLine.Start);
+ Point selectionScreenPos = docView.TextView.VisualElement.PointToScreen(
+ new Point(selectionLine.Left - docView.TextView.ViewportLeft,
+ selectionLine.Top - docView.TextView.ViewportTop));
+
+ var start = docView.TextView.TextViewLines.GetCharacterBounds(snapshotLine.Start);
+
+ // highlight the selected codeblock
+ TextHighlighter? highlighter = TextHighlighter.GetInstance(docView.TextView);
+ highlighter?.AddHighlight(snapshotLine.Extent);
+ var dialog = RefactorCodeDialogWindow.GetOrCreate();
+ string? prompt =
+ await dialog.ShowAndGetPromptAsync(languageInfo, selectionScreenPos.X, selectionScreenPos.Y);
+
+ highlighter?.ClearAll();
+
+ await ResolveCodeBlock(startLine);
+ // user did not select any of the prompt
+ if (prompt == null) return;
+ if (functionInfo != null)
+ {
+ controller.RefactorFunctionAsync(
+ prompt, docView.FilePath, functionInfo);
+ }
+ else
+ {
+ if (classInfo == null) return;
+ CodeBlockInfo codeBlockInfo = ClassToCodeBlock(classInfo);
+
+ await controller.RefactorCodeBlockAsync(
+ prompt, docView.FilePath, languageInfo.Type, codeBlockInfo);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(ex.ToString());
+ }
+ }
+}
+
+[Command(PackageIds.ExplainSelectionCodeBlock)]
+internal class ExplainSelectionCodeBlock : BaseCommandCodeLens
+{
+ protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)
+ {
+
+ try
+ {
+ LanguageServerController controller =
+ (Package as CodeiumVSPackage).LanguageServer.Controller;
+
+ if (e.InValue != null)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(e.InValue.ToString());
+ var ctx = e.InValue as CodeLensDescriptorContext;
+ int startPos = ctx.ApplicableSpan.Value.Start;
+ ITextSnapshotLine line = docView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPos);
+ int startLine = line.LineNumber;
+
+ await ResolveCodeBlock(startLine);
+ if (functionInfo != null)
+ {
+ controller.ExplainFunctionAsync(docView.FilePath, functionInfo);
+ }
+ else
+ {
+ if (classInfo == null) return;
+ CodeBlockInfo codeBlockInfo = ClassToCodeBlock(classInfo);
+ controller.ExplainCodeBlockAsync(
+ docView.FilePath, languageInfo.Type, codeBlockInfo);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(ex.ToString());
+ }
+ }
+}
+
+
+[Command(PackageIds.GenerateSelectionFunctionDocstring)]
+internal class GenerateSelectionFunctionDocstring : BaseCommandCodeLens
+{
+ protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)
+ {
+
+ try
+ {
+ LanguageServerController controller =
+ (Package as CodeiumVSPackage).LanguageServer.Controller;
+
+ if (e.InValue != null)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(e.InValue.ToString());
+ var ctx = e.InValue as CodeLensDescriptorContext;
+ int startPos = ctx.ApplicableSpan.Value.Start;
+ ITextSnapshotLine line = docView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPos);
+ int startLine = line.LineNumber;
+
+ await ResolveCodeBlock(startLine);
+ if (functionInfo != null)
+ {
+ controller.GenerateFunctionDocstringAsync(docView.FilePath, functionInfo);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ await CodeiumVSPackage.Instance.LogAsync(ex.ToString());
+ }
+ }
+}
[Command(PackageIds.GenerateFunctionUnitTest)]
internal class CommandGenerateFunctionUnitTest
: BaseCommandContextMenu
diff --git a/CodeiumVS/LanguageServer/LanguageServer.cs b/CodeiumVS/LanguageServer/LanguageServer.cs
index 89056ed..511c59a 100644
--- a/CodeiumVS/LanguageServer/LanguageServer.cs
+++ b/CodeiumVS/LanguageServer/LanguageServer.cs
@@ -818,6 +818,7 @@ public Metadata GetMetadata()
api_key = _metadata.api_key,
ide_name = _metadata.ide_name,
ide_version = _metadata.ide_version,
+
extension_name = _metadata.extension_name,
extension_version = _metadata.extension_version,
session_id = _metadata.session_id,
@@ -827,7 +828,7 @@ public Metadata GetMetadata()
public async Task?>
GetFunctionsAsync(string absolutePath, string text, Languages.LangInfo language,
- int cursorPosition, string lineEnding, CancellationToken token)
+ int cursorPosition, CancellationToken token)
{
if (!_initializedWorkspace)
{
diff --git a/CodeiumVS/SuggestionUI/SuggestionTagger.cs b/CodeiumVS/SuggestionUI/SuggestionTagger.cs
index 9bfbd31..fd0a37a 100644
--- a/CodeiumVS/SuggestionUI/SuggestionTagger.cs
+++ b/CodeiumVS/SuggestionUI/SuggestionTagger.cs
@@ -68,49 +68,68 @@ private InlineGreyTextTagger GetTagger()
public bool SetSuggestion(String newSuggestion, int caretPoint)
{
- newSuggestion = newSuggestion.TrimEnd();
- newSuggestion = newSuggestion.Replace("\r", "");
- ClearSuggestion();
+ try
+ {
+ // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll
+ newSuggestion = newSuggestion.TrimEnd();
+ newSuggestion = newSuggestion.Replace("\r", "");
+ ClearSuggestion();
- int lineN = GetCurrentTextLine();
+ int lineN = GetCurrentTextLine();
- if (lineN < 0) return false;
+ if (lineN < 0) return false;
- String untrim = buffer.CurrentSnapshot.GetLineFromLineNumber(lineN).GetText();
+ String untrim = buffer.CurrentSnapshot.GetLineFromLineNumber(lineN).GetText();
- virtualText = "";
- if (String.IsNullOrWhiteSpace(untrim) && untrim.Length < caretPoint)
- {
- virtualText = new string(' ', caretPoint - untrim.Length);
- }
- String line = untrim.TrimStart();
- int offset = untrim.Length - line.Length;
+ virtualText = "";
+ if (String.IsNullOrWhiteSpace(untrim) && untrim.Length < caretPoint)
+ {
+ virtualText = new string(' ', caretPoint - untrim.Length);
+ }
+ String line = untrim.TrimStart();
+ int offset = untrim.Length - line.Length;
- caretPoint = Math.Max(0, caretPoint - offset);
+ caretPoint = Math.Max(0, caretPoint - offset);
- String combineSuggestion = line + newSuggestion;
- if (line.Length - caretPoint > 0)
- {
- String currentText = line.Substring(0, caretPoint);
- combineSuggestion = currentText + newSuggestion;
- userEndingText = line.Substring(caretPoint).Trim();
- var userIndex = newSuggestion.IndexOf(userEndingText);
+ String combineSuggestion = line + newSuggestion;
+ if (line.Length - caretPoint > 0)
+ {
+ String currentText = line.Substring(0, caretPoint);
+ combineSuggestion = currentText + newSuggestion;
+ userEndingText = line.Substring(caretPoint).Trim();
+ var userIndex = newSuggestion.IndexOf(userEndingText);
- if (userIndex < 0) { return false; }
- userIndex += currentText.Length;
+ if (userIndex < 0) { return false; }
+ userIndex += currentText.Length;
- this.userIndex = userIndex;
- isTextInsertion = true;
- insertionPoint = line.Length - caretPoint;
+ this.userIndex = userIndex;
+ isTextInsertion = true;
+ insertionPoint = line.Length - caretPoint;
+ }
+ else { isTextInsertion = false; }
+ var suggestionLines = combineSuggestion.Split('\n');
+ suggestion = new Tuple(combineSuggestion, suggestionLines);
+ return Update();
+ }catch (Exception ex)
+ {
+ CodeiumVSPackage.Instance?.LogAsync("Exception: " + ex.ToString());
+ return false;
}
- else { isTextInsertion = false; }
- var suggestionLines = combineSuggestion.Split('\n');
- suggestion = new Tuple(combineSuggestion, suggestionLines);
- return Update();
}
public bool OnSameLine() { return GetCurrentTextLine() == currentTextLineN; }
- private void LostFocus(object sender, EventArgs e) { ClearSuggestion(); }
+
+ private void LostFocus(object sender, EventArgs e)
+ {
+ try
+ {
+ ClearSuggestion();
+ }
+ catch (Exception ex)
+ {
+ CodeiumVSPackage.Instance?.LogAsync("Exception: " + ex.ToString());
+ }
+ }
public SuggestionTagger(IWpfTextView view, ITextBuffer buffer)
{
@@ -173,11 +192,17 @@ public IEnumerable> GetTags(NormalizedSnapshotSpanCollec
// triggers when the editor text buffer changes
void BufferChanged(object sender, TextContentChangedEventArgs e)
{
- // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll
- // eventually get another change event).
- if (e.After != buffer.CurrentSnapshot) return;
-
- this.Update();
+ try
+ {
+ // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll
+ // eventually get another change event).
+ if (e.After != buffer.CurrentSnapshot) return;
+ this.Update();
+ }
+ catch (Exception ex)
+ {
+ CodeiumVSPackage.Instance?.LogAsync("Exception: " + ex.ToString());
+ }
}
TextRunProperties GetTextFormat()
@@ -253,88 +278,88 @@ void AddInsertionTextBlock(int start, int end, string line)
// Updates the grey text
public void UpdateAdornment(IWpfTextView view, string userText, int suggestionStart)
{
- stackPanel.Children.Clear();
- GetTagger().ClearAdornment();
- for (int i = suggestionStart; i < suggestion.Item2.Length; i++)
- {
- string line = suggestion.Item2[i];
-
- if (i == 0)
+ try
+ {
+ stackPanel.Children.Clear();
+ GetTagger().ClearAdornment();
+ for (int i = suggestionStart; i < suggestion.Item2.Length; i++)
{
- int offset = line.Length - line.TrimStart().Length;
+ string line = suggestion.Item2[i];
- if (isTextInsertion && suggestionIndex < userIndex)
+ if (i == 0)
{
- if (suggestionIndex > 0 && suggestionIndex < line.Length && char.IsWhiteSpace(line[suggestionIndex - 1]) &&
- userText.Length > insertionPoint + 1 &&
- !char.IsWhiteSpace(userText[userText.Length - insertionPoint - 1]))
- {
- suggestionIndex--;
- }
- AddInsertionTextBlock(suggestionIndex + offset, userIndex, line);
- if (line.Length > userIndex + 1)
- {
- AddSuffixTextBlocks(
- userIndex + userEndingText.Trim().Length, line, userText);
- }
- else { stackPanel.Children.Add(CreateTextBox("", greyBrush)); }
- }
- else
- {
- if (String.IsNullOrEmpty(line))
+ int offset = line.Length - line.TrimStart().Length;
+
+ if (isTextInsertion && suggestionIndex < userIndex)
{
- stackPanel.Children.Add(CreateTextBox("", greyBrush));
+ if (suggestionIndex > 0 && suggestionIndex < line.Length && char.IsWhiteSpace(line[suggestionIndex - 1]) &&
+ userText.Length > insertionPoint + 1 &&
+ !char.IsWhiteSpace(userText[userText.Length - insertionPoint - 1]))
+ {
+ suggestionIndex--;
+ }
+ AddInsertionTextBlock(suggestionIndex + offset, userIndex, line);
+ if (line.Length > userIndex + 1)
+ {
+ AddSuffixTextBlocks(
+ userIndex + userEndingText.Trim().Length, line, userText);
+ }
+ else { stackPanel.Children.Add(CreateTextBox("", greyBrush)); }
}
else
{
- String suggestedLine =
- virtualText.Length > 0 ? virtualText + line.TrimStart() : line;
- AddSuffixTextBlocks(userText.Length > 0 ? suggestionIndex + offset : 0,
- suggestedLine,
- userText);
+ if (String.IsNullOrEmpty(line))
+ {
+ stackPanel.Children.Add(CreateTextBox("", greyBrush));
+ }
+ else
+ {
+ String suggestedLine =
+ virtualText.Length > 0 ? virtualText + line.TrimStart() : line;
+ AddSuffixTextBlocks(userText.Length > 0 ? suggestionIndex + offset : 0,
+ suggestedLine,
+ userText);
+ }
}
}
+ else { stackPanel.Children.Add(CreateTextBox(line, greyBrush)); }
}
- else { stackPanel.Children.Add(CreateTextBox(line, greyBrush)); }
- }
- this.adornmentLayer.RemoveAllAdornments();
+ this.adornmentLayer.RemoveAllAdornments();
- // usually only happens the moment a bunch of text has rentered such as an undo operation
- try
- {
- ITextSnapshotLine snapshotLine =
- view.TextSnapshot.GetLineFromLineNumber(currentTextLineN);
- var start = view.TextViewLines.GetCharacterBounds(snapshotLine.Start);
+ // usually only happens the moment a bunch of text has rentered such as an undo operation
+ ITextSnapshotLine snapshotLine =
+ view.TextSnapshot.GetLineFromLineNumber(currentTextLineN);
+ var start = view.TextViewLines.GetCharacterBounds(snapshotLine.Start);
- // Place the image in the top left hand corner of the line
- Canvas.SetLeft(stackPanel, start.Left);
- Canvas.SetTop(stackPanel, start.TextTop);
- var span = snapshotLine.Extent;
- // Add the image to the adornment layer and make it relative to the viewport
- this.adornmentLayer.AddAdornment(
- AdornmentPositioningBehavior.TextRelative, span, null, stackPanel, null);
+ // Place the image in the top left hand corner of the line
+ Canvas.SetLeft(stackPanel, start.Left);
+ Canvas.SetTop(stackPanel, start.TextTop);
+ var span = snapshotLine.Extent;
+ // Add the image to the adornment layer and make it relative to the viewport
+ this.adornmentLayer.AddAdornment(
+ AdornmentPositioningBehavior.TextRelative, span, null, stackPanel, null);
}
catch (Exception e)
- {
- Debug.Write(e);
+ { Debug.Write(e);
}
}
// Adds grey text to display
private void OnSizeChanged(object sender, EventArgs e)
{
- if (!showSuggestion) { return; }
- foreach (TextBlock block in stackPanel.Children)
+ try
{
- FormatText(block);
- }
+ if (!showSuggestion) { return; }
- ITextSnapshotLine snapshotLine = view.TextSnapshot.GetLineFromLineNumber(currentTextLineN);
+ foreach (TextBlock block in stackPanel.Children)
+ {
+ FormatText(block);
+ }
+
+ ITextSnapshotLine snapshotLine = view.TextSnapshot.GetLineFromLineNumber(currentTextLineN);
- try
- {
var start = view.TextViewLines.GetCharacterBounds(snapshotLine.Start);
InlineGreyTextTagger inlineTagger = GetTagger();
@@ -358,9 +383,9 @@ private void OnSizeChanged(object sender, EventArgs e)
AdornmentPositioningBehavior.TextRelative, span, null, stackPanel, null);
}
}
- catch (ArgumentOutOfRangeException)
+ catch (Exception ex)
{
- Debug.Print("Error argument out of range");
+ CodeiumVSPackage.Instance?.LogAsync("Exception: " + ex.ToString());
}
}
@@ -398,12 +423,12 @@ public bool Update()
// else
// clear suggestions
- int suggestionIndex =
+ int newIndex =
StringCompare.CheckSuggestion(suggestion.Item1, line, isTextInsertion, insertionPoint);
- if (suggestionIndex >= 0)
+ if (newIndex >= 0)
{
this.currentTextLineN = textLineN;
- this.suggestionIndex = suggestionIndex;
+ this.suggestionIndex = newIndex;
ShowSuggestion(untrimLine, 0);
return true;
}
@@ -415,20 +440,31 @@ public bool Update()
// Adds the grey text to the file replacing current line in the process
public bool CompleteText()
{
- if (!showSuggestion || suggestion == null) { return false; }
+ try
+ {
+ if (!showSuggestion || suggestion == null)
+ {
+ return false;
+ }
- String untrimLine = this.snapshot.GetLineFromLineNumber(currentTextLineN).GetText();
- String line = untrimLine.Trim();
+ String untrimLine = this.snapshot.GetLineFromLineNumber(currentTextLineN).GetText();
+ String line = untrimLine.Trim();
- int suggestionLineN =
- StringCompare.CheckSuggestion(suggestion.Item1, line, isTextInsertion, insertionPoint);
- if (suggestionLineN >= 0)
+ int suggestionLineN =
+ StringCompare.CheckSuggestion(suggestion.Item1, line, isTextInsertion, insertionPoint);
+ if (suggestionLineN >= 0)
+ {
+ int diff = untrimLine.Length - untrimLine.TrimStart().Length;
+ string whitespace =
+ String.IsNullOrWhiteSpace(untrimLine) ? "" : untrimLine.Substring(0, diff);
+ ReplaceText(whitespace + suggestion.Item1, currentTextLineN);
+ return true;
+ }
+
+ }
+ catch (Exception e)
{
- int diff = untrimLine.Length - untrimLine.TrimStart().Length;
- string whitespace =
- String.IsNullOrWhiteSpace(untrimLine) ? "" : untrimLine.Substring(0, diff);
- ReplaceText(whitespace + suggestion.Item1, currentTextLineN);
- return true;
+ CodeiumVSPackage.Instance?.LogAsync("Exception: " + e.ToString());
}
return false;
@@ -476,15 +512,23 @@ void ShowSuggestion(String text, int suggestionLineStart)
// removes the suggestion
public void ClearSuggestion()
{
- if (!showSuggestion) return;
- InlineGreyTextTagger inlineTagger = GetTagger();
- inlineTagger.ClearAdornment();
- inlineTagger.MarkDirty();
- suggestion = null;
- adornmentLayer.RemoveAllAdornments();
- showSuggestion = false;
+ try
+ {
+ if (!showSuggestion) return;
+ InlineGreyTextTagger inlineTagger = GetTagger();
+ inlineTagger.ClearAdornment();
+ inlineTagger.MarkDirty();
+ suggestion = null;
+ adornmentLayer.RemoveAllAdornments();
+ showSuggestion = false;
- MarkDirty();
+ MarkDirty();
+
+ }
+ catch (Exception ex)
+ {
+
+ }
}
// triggers refresh of the screen
diff --git a/CodeiumVS/SuggestionUI/TextViewListener.cs b/CodeiumVS/SuggestionUI/TextViewListener.cs
index 48d11f3..be4fad1 100644
--- a/CodeiumVS/SuggestionUI/TextViewListener.cs
+++ b/CodeiumVS/SuggestionUI/TextViewListener.cs
@@ -117,7 +117,7 @@ public async void GetCompletion()
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
suggestionIndex = 0;
currentCompletionID = suggestions[0].Item2;
- tagger.SetSuggestion(suggestions[0].Item1, characterN);
+ var valid = tagger.SetSuggestion(suggestions[0].Item1, characterN);
}
await package.LogAsync("Generated " + list.Count + $" proposals");
@@ -225,6 +225,11 @@ private void OnSuggestionAccepted(String proposalId)
.FireAndForget(true);
}
+ public LangInfo GetLanguage()
+ {
+ return _language;
+ }
+
private void UpdateRequestTokenSource(CancellationTokenSource newSource)
{
if (currentCancellTokenSource != null)
@@ -263,6 +268,9 @@ internal CodeiumCompletionHandler(IVsTextView textViewAdapter, ITextView view,
if (_document != null)
{
+ CodeiumVSPackage.Instance.LogAsync("CodeiumCompletionHandler filepath = " + _document.FilePath);
+
+ provider.documentDictionary.Add(_document.FilePath.ToLower(), _document);
_document.FileActionOccurred += OnFileActionOccurred;
_document.TextBuffer.ContentTypeChanged += OnContentTypeChanged;
RefreshLanguage();
@@ -291,21 +299,36 @@ internal CodeiumCompletionHandler(IVsTextView textViewAdapter, ITextView view,
private void CaretUpdate(object sender, CaretPositionChangedEventArgs e)
{
- var tagger = GetTagger();
- if(tagger == null) { return; }
- if (CompleteSuggestionCommand != null && CompleteSuggestionCommand.Bindings is object[] bindings && bindings.Length > 0)
+ try
{
- tagger.ClearSuggestion();
- return;
- }
+ var tagger = GetTagger();
+ if (tagger == null)
+ {
+ return;
+ }
- var key = GetAsyncKeyState(0x09);
- if ((0x8000 & key) > 0)
- {
- CompleteSuggestion(false);
- }else if (!tagger.OnSameLine())
+ if (CompleteSuggestionCommand != null && CompleteSuggestionCommand.Bindings is object[] bindings &&
+ bindings.Length > 0)
+ {
+ tagger.ClearSuggestion();
+ return;
+ }
+
+ var key = GetAsyncKeyState(0x09);
+ if ((0x8000 & key) > 0)
+ {
+ CompleteSuggestion(false);
+ }
+ else if (!tagger.OnSameLine())
+ {
+ tagger.ClearSuggestion();
+ }
+ }
+ catch (Exception ex)
{
- tagger.ClearSuggestion();
+ ThreadHelper.JoinableTaskFactory
+ .RunAsync(async delegate { await CodeiumVSPackage.Instance.LogAsync(ex.ToString()); })
+ .FireAndForget(true);
}
}
@@ -327,36 +350,47 @@ private void RefreshLanguage()
public async void ShowNextSuggestion()
{
- if (suggestions != null && suggestions.Count > 1)
+ try
{
+ if (suggestions != null && suggestions.Count > 1)
+ {
- await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
- var oldSuggestion = suggestionIndex;
- suggestionIndex = (suggestionIndex + 1) % suggestions.Count;
- currentCompletionID = suggestions[suggestionIndex].Item2;
+ var oldSuggestion = suggestionIndex;
+ suggestionIndex = (suggestionIndex + 1) % suggestions.Count;
+ currentCompletionID = suggestions[suggestionIndex].Item2;
- SuggestionTagger tagger = GetTagger();
-
- int lineN, characterN;
- int res = _textViewAdapter.GetCaretPos(out lineN, out characterN);
+ SuggestionTagger tagger = GetTagger();
- if (res != VSConstants.S_OK)
- {
- suggestionIndex = oldSuggestion;
- currentCompletionID = suggestions[suggestionIndex].Item2;
- return;
- }
+ int lineN, characterN;
+ int res = _textViewAdapter.GetCaretPos(out lineN, out characterN);
- bool validSuggestion = tagger.SetSuggestion(suggestions[suggestionIndex].Item1, characterN);
- if (!validSuggestion)
- {
- suggestionIndex = oldSuggestion;
- currentCompletionID = suggestions[suggestionIndex].Item2;
+ if (res != VSConstants.S_OK)
+ {
+ suggestionIndex = oldSuggestion;
+ currentCompletionID = suggestions[suggestionIndex].Item2;
+ return;
+ }
+
+ bool validSuggestion = tagger.SetSuggestion(suggestions[suggestionIndex].Item1, characterN);
+ if (!validSuggestion)
+ {
+ suggestionIndex = oldSuggestion;
+ currentCompletionID = suggestions[suggestionIndex].Item2;
- tagger.SetSuggestion(suggestions[suggestionIndex].Item1, characterN);
+ tagger.SetSuggestion(suggestions[suggestionIndex].Item1, characterN);
+ }
}
}
+ catch (Exception ex)
+ {
+ ThreadHelper.JoinableTaskFactory
+ .RunAsync(async delegate { await CodeiumVSPackage.Instance.LogAsync(ex.ToString()); })
+ .FireAndForget(true);
+
+ }
+
}
public bool CompleteSuggestion(bool checkLine = true)
@@ -487,7 +521,6 @@ public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pv
CheckSuggestionUpdate(nCmdID);
-
// make a copy of this so we can look at it after forwarding some commands
uint commandID = nCmdID;
char typedChar = char.MinValue;
@@ -590,16 +623,20 @@ internal ICompletionBroker CompletionBroker {
[Import]
internal ITextDocumentFactoryService documentFactory = null;
- public void VsTextViewCreated(IVsTextView textViewAdapter)
- {
- ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
- if (textView == null) return;
+ internal static TextViewListener? Instance { get; private set; }
- Func createCommandHandler = delegate()
- {
- return new CodeiumCompletionHandler(textViewAdapter, textView, this);
- };
- textView.TextBuffer.Properties.GetOrCreateSingletonProperty(typeof(CodeiumCompletionHandler), createCommandHandler);
- }
+ public Dictionary documentDictionary = new Dictionary();
+ public void VsTextViewCreated(IVsTextView textViewAdapter)
+ {
+ Instance = this;
+ ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
+ if (textView == null) return;
+
+ Func createCommandHandler = delegate()
+ {
+ return new CodeiumCompletionHandler(textViewAdapter, textView, this);
+ };
+ textView.TextBuffer.Properties.GetOrCreateSingletonProperty(typeof(CodeiumCompletionHandler), createCommandHandler);
}
}
+}
diff --git a/CodeiumVS/VSCommandTable.cs b/CodeiumVS/VSCommandTable.cs
index 3ad52fa..6e3afc2 100644
--- a/CodeiumVS/VSCommandTable.cs
+++ b/CodeiumVS/VSCommandTable.cs
@@ -36,6 +36,10 @@ internal sealed partial class PackageIds
public const int GenerateFunctionUnitTest = 0x0107;
public const int ShowNextSuggestion = 0x0108;
public const int CompleteSuggestion = 0x0109;
+ public const int RefactorSelectionCodeBlock = 0x0110;
+ public const int ExplainSelectionCodeBlock = 0x0111;
+ public const int GenerateSelectionFunctionDocstring = 0x0112;
public const int DebugButton = 0x0600;
+
}
}
diff --git a/CodeiumVS/VSCommandTable.vsct b/CodeiumVS/VSCommandTable.vsct
index 2557689..631be90 100644
--- a/CodeiumVS/VSCommandTable.vsct
+++ b/CodeiumVS/VSCommandTable.vsct
@@ -157,6 +157,38 @@
Codeium.CompleteSuggestion
+
+
+
+
+
+
+
+
+