Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
saranshsaini committed Dec 18, 2024
1 parent d761d93 commit 180e974
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 60 deletions.
195 changes: 136 additions & 59 deletions CodeiumVS/LanguageServer/LanguageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class LanguageServer

public readonly LanguageServerController Controller;


public LanguageServer()
{
_package = CodeiumVSPackage.Instance;
Expand Down Expand Up @@ -158,7 +159,7 @@ public async Task SignInAsync()

// TODO: should we use timeout = Timeout.InfiniteTimeSpan? default value is 100s (1m40s)
GetAuthTokenResponse? result =
await RequestCommandAsync<GetAuthTokenResponse>("GetAuthToken", new {});
await RequestCommandAsync<GetAuthTokenResponse>("GetAuthToken", new { });

if (result == null)
{
Expand Down Expand Up @@ -302,7 +303,7 @@ await _package.LogAsync(
KnownMonikers.StatusError,
true,
null,
[..actions, ..NotificationInfoBar.SupportActions]);
[.. actions, .. NotificationInfoBar.SupportActions]);
}
else
{
Expand Down Expand Up @@ -373,7 +374,8 @@ private void ThreadDownloadLanguageServer(IVsThreadedWaitDialog4 progressDialog)
webClient.DownloadFileCompleted += (s, e) =>
{
ThreadHelper.JoinableTaskFactory
.RunAsync(async delegate {
.RunAsync(async delegate
{
await ThreadDownload_OnCompletedAsync(e, progressDialog, downloadDest);
})
.FireAndForget();
Expand Down Expand Up @@ -591,7 +593,7 @@ await _package.LogAsync(
KnownMonikers.StatusError,
true,
null,
[..actions, ..NotificationInfoBar.SupportActions]);
[.. actions, .. NotificationInfoBar.SupportActions]);

return;
}
Expand Down Expand Up @@ -739,73 +741,138 @@ private async Task InitializeTrackedWorkspaceAsync()
DTE dte = (DTE)ServiceProvider.GlobalProvider.GetService(typeof(DTE));
await _package.LogAsync($"Number of top-level projects: {dte.Solution.Projects.Count}");

List<string> processedProjects = new List<string>();
var trackedProjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var documents = dte.Documents;
var openFilePaths = new HashSet<string>();
if (_package.SettingsPage.IndexOpenFiles)
{
foreach (EnvDTE.Document doc in documents)
{
await _package.LogAsync($"Open File: {doc.Path}");
openFilePaths.Add(doc.Path);
}
}

var inputProjectsToIndex = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
string projectListPath = _package.SettingsPage.IndexingFilesListPath.Trim();
try
{
if (!string.IsNullOrEmpty(projectListPath) && File.Exists(projectListPath))
{
string[] lines = File.ReadAllLines(projectListPath);
string[] lines = File.ReadAllLines(projectListPath);
foreach (string line in lines)
{
string trimmedLine = line.Trim();
if (!string.IsNullOrEmpty(trimmedLine))
{
trackedProjects.Add(trimmedLine);
inputProjectsToIndex.Add(trimmedLine);
}
}
await _package.LogAsync($"Number of Projects loaded from {projectListPath}: {trackedProjects.Count}");
await _package.LogAsync($"Number of Projects loaded from {projectListPath}: {inputProjectsToIndex.Count}");
}
}
catch (Exception ex)
{
await _package.LogAsync($"Error reading project list: {ex.Message}");
}
// Note: If you have projects in the indexing list, but none ofthe projects in the sln are actually in that list, then this function will get called on every completion generation.
// This is because _initializedWorkspace will never be set to True. That should never happen though so not handling it.
async Task ProcessProjectAsync(EnvDTE.Project project)

List<string> projectsToIndex = await GetFilesToIndex(inputProjectsToIndex, openFilePaths, dte);
await _package.LogAsync($"Number of projects to index: {projectsToIndex.Count}");

for (int i = 0; i < projectsToIndex.Count; i++)
{
try
{
string projectFullName = project.FullName;
string projectName = Path.GetFileNameWithoutExtension(projectFullName);

if (!string.IsNullOrEmpty(projectFullName) &&
!processedProjects.Contains(projectFullName) &&
(trackedProjects.Count == 0 || trackedProjects.Contains(projectName)))
await _package.LogAsync($"Processing Project {i + 1} of {projectsToIndex.Count}: {projectsToIndex[i]}");
AddTrackedWorkspaceResponse response = await AddTrackedWorkspaceAsync(projectsToIndex[i]);
if (response != null)
{
processedProjects.Add(projectFullName);
string projectDir = Path.GetDirectoryName(projectFullName);
await _package.LogAsync($"Processing Project {projectName} in Project Dir: {projectDir}");
AddTrackedWorkspaceResponse response = await AddTrackedWorkspaceAsync(projectDir);
if (response != null)
{
_initializedWorkspace = true;
}
_initializedWorkspace = true;
}
}
catch (Exception ex)
{
await _package.LogAsync($"Error processing project {i + 1} of {projectsToIndex.Count}: {ex.Message}");
}
}
}

// Process sub-projects (e.g., project references)
foreach (EnvDTE.ProjectItem item in project.ProjectItems)
private async Task<List<string>> GetFilesToIndex(HashSet<string> inputProjectsToIndex, HashSet<string> openFilePaths, DTE dte)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
int maxToIndex = 15;
HashSet<string> specifiedProjectsToIndexPath = new HashSet<string>();
HashSet<string> openFilesProjectsToIndexPath = new HashSet<string>();
HashSet<string> remainingProjectsToIndexPath = new HashSet<string>();
HashSet<string> processedProjects = new HashSet<string>();
async Task AddFilesToIndexLists(EnvDTE.Project project)
{
if (specifiedProjectsToIndexPath.Count == inputProjectsToIndex.Count && openFilePaths.Count == 0 && (specifiedProjectsToIndexPath.Count + remainingProjectsToIndexPath.Count + openFilesProjectsToIndexPath.Count) > maxToIndex)
{
return;
}
string projectFullName = project.FullName;
string projectName = Path.GetFileNameWithoutExtension(projectFullName);
if (!string.IsNullOrEmpty(projectFullName) && !processedProjects.Contains(projectFullName))
{
string projectDir = Path.GetDirectoryName(projectFullName);

// There are three cases.
// 1. The project is in the list of projects to index passed in by the user. These take priority. The entire solution is searched until all are found.
// 2. Find the project the open file is a member of. Not sure if nested projects could match the same file multiple times so delete from the set when found.
// 3. Any other project. Tops it up to the max amount to index if the previous two cases didnt.
if (inputProjectsToIndex.Contains(projectName))
{
await _package.LogAsync($"Found in input list {projectName}");
specifiedProjectsToIndexPath.Add(projectDir);
}
else if (openFilePaths.Count != 0)
{
if (item.SubProject != null)
string matchingFile = null;
foreach (var filePath in openFilePaths)
{
await ProcessProjectAsync(item.SubProject);
if (filePath.StartsWith(projectDir, StringComparison.OrdinalIgnoreCase))
{
await _package.LogAsync($"Found in open files {filePath}");
matchingFile = filePath;
break;
}
}
if (!string.IsNullOrEmpty(matchingFile))
{
openFilesProjectsToIndexPath.Add(projectDir);
openFilePaths.Remove(matchingFile);
}
}
else
{
await _package.LogAsync($"Found in remaining {projectName}");
remainingProjectsToIndexPath.Add(projectDir);
}
processedProjects.Add(projectFullName);
}
catch (Exception ex)

foreach (EnvDTE.ProjectItem item in project.ProjectItems)
{
await _package.LogAsync("Error: Failed to initialize tracked workspace: " + ex.Message);
if (item.SubProject != null)
{
await AddFilesToIndexLists(item.SubProject);

}
}
}

foreach (EnvDTE.Project project in dte.Solution.Projects)
{
await ProcessProjectAsync(project);
}
await AddFilesToIndexLists(project);
}
List<string> result = new List<string>();
result.AddRange(specifiedProjectsToIndexPath);
result.AddRange(openFilesProjectsToIndexPath);
result.AddRange(remainingProjectsToIndexPath);
return result;
}


private async Task<T?> RequestCommandAsync<T>(string command, object data,
CancellationToken cancellationToken = default)
{
Expand All @@ -826,21 +893,28 @@ public async Task<IList<CompletionItem>?>
var uri = new System.Uri(absolutePath);
var absoluteUri = uri.AbsoluteUri;
GetCompletionsRequest data =
new() { metadata = GetMetadata(),
document = new() { text = text,
editor_language = language.Name,
language = language.Type,
cursor_offset = (ulong)cursorPosition,
line_ending = lineEnding,
absolute_path = absolutePath,
absolute_uri = absoluteUri,
relative_path = Path.GetFileName(absolutePath) },
editor_options = new() {
tab_size = (ulong)tabSize,
insert_spaces = insertSpaces,
disable_autocomplete_in_comments =
new()
{
metadata = GetMetadata(),
document = new()
{
text = text,
editor_language = language.Name,
language = language.Type,
cursor_offset = (ulong)cursorPosition,
line_ending = lineEnding,
absolute_path = absolutePath,
absolute_uri = absoluteUri,
relative_path = Path.GetFileName(absolutePath)
},
editor_options = new()
{
tab_size = (ulong)tabSize,
insert_spaces = insertSpaces,
disable_autocomplete_in_comments =
!_package.SettingsPage.EnableCommentCompletion,
} };
}
};

GetCompletionsResponse? result =
await RequestCommandAsync<GetCompletionsResponse>("GetCompletions", data, token);
Expand All @@ -857,7 +931,7 @@ public async Task AcceptCompletionAsync(string completionId)

public async Task<GetProcessesResponse?> GetProcessesAsync()
{
return await RequestCommandAsync<GetProcessesResponse>("GetProcesses", new {});
return await RequestCommandAsync<GetProcessesResponse>("GetProcesses", new { });
}

public async Task<AddTrackedWorkspaceResponse?> AddTrackedWorkspaceAsync(string workspacePath)
Expand All @@ -868,16 +942,19 @@ public async Task AcceptCompletionAsync(string completionId)

public Metadata GetMetadata()
{
return new() { request_id = _metadata.request_id++,
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,
locale = _metadata.locale,
disable_telemetry = _metadata.disable_telemetry };
return new()
{
request_id = _metadata.request_id++,
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,
locale = _metadata.locale,
disable_telemetry = _metadata.disable_telemetry
};
}

public async Task<IList<FunctionInfo>?>
Expand Down
16 changes: 16 additions & 0 deletions CodeiumVS/SettingsPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class SettingsPage : DialogPage
private bool enableCodeLens = true;
private int indexingMaxFileCount = 5000;
private string indexingFilesListPath = "";
private bool indexOpenFiles = true;

[Category("Codeium")]
[DisplayName("Enterprise Mode")]
Expand Down Expand Up @@ -154,4 +155,19 @@ public string IndexingFilesListPath
indexingFilesListPath = value;
}
}
[Category("Codeium")]
[DisplayName("Index Open Files")]
[Description(
"Complete path to a .txt file that contains a line separated list of file paths to index. Leave blank to index full solution.")]
public bool IndexOpenFiles
{
get
{
return indexOpenFiles;
}
set
{
indexOpenFiles = value;
}
}
}
2 changes: 1 addition & 1 deletion CodeiumVS/SuggestionUI/SuggestionTagger.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
Expand Down

0 comments on commit 180e974

Please sign in to comment.