Skip to content

Commit

Permalink
Improve Project Parsing Logic (#157)
Browse files Browse the repository at this point in the history
Improved Logic
  • Loading branch information
saranshsaini authored Jan 22, 2025
1 parent fd93c5a commit a979eda
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 28 deletions.
1 change: 1 addition & 0 deletions CodeiumVS/CodeiumVS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
Expand Down
113 changes: 87 additions & 26 deletions CodeiumVS/LanguageServer/LanguageServer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CodeiumVS.Packets;
using CodeiumVS.Packets;
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Imaging;
Expand All @@ -12,6 +12,7 @@
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
Expand All @@ -20,6 +21,7 @@
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace CodeiumVS;

Expand Down Expand Up @@ -753,7 +755,7 @@ private async Task InitializeTrackedWorkspaceAsync()
}
}

var inputProjectsToIndex = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var inputFilesToIndex = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
string projectListPath = _package.SettingsPage.IndexingFilesListPath.Trim();
try
{
Expand All @@ -765,18 +767,22 @@ private async Task InitializeTrackedWorkspaceAsync()
string trimmedLine = line.Trim();
if (!string.IsNullOrEmpty(trimmedLine))
{
inputProjectsToIndex.Add(trimmedLine);
if (Path.IsPathRooted(trimmedLine))
{
inputFilesToIndex.Add(trimmedLine);
}
}
}
await _package.LogAsync($"Number of Projects loaded from {projectListPath}: {inputProjectsToIndex.Count}");
await _package.LogAsync($"Loaded from {inputFilesToIndex.Count} files");
}
}
catch (Exception ex)
{
await _package.LogAsync($"Error reading project list: {ex.Message}");
}

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

for (int i = 0; i < projectsToIndex.Count; i++)
Expand All @@ -797,17 +803,16 @@ private async Task InitializeTrackedWorkspaceAsync()
}
}

private async Task<List<string>> GetFilesToIndex(HashSet<string> inputProjectsToIndex, HashSet<string> openFilePaths, DTE dte)
private async Task<List<string>> GetFilesToIndex(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)
if (openFilePaths.Count == 0 && (openFilesProjectsToIndexPath.Count + remainingProjectsToIndexPath.Count) >= maxToIndex)
{
return;
}
Expand All @@ -816,38 +821,95 @@ async Task AddFilesToIndexLists(EnvDTE.Project project)
if (!string.IsNullOrEmpty(projectFullName) && !processedProjects.Contains(projectFullName))
{
string projectDir = Path.GetDirectoryName(projectFullName);
HashSet<string> sourceDirectories = new HashSet<string> { projectDir };

// 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))
// Parse the csproj file to find all source directories
if (File.Exists(projectFullName) && (projectFullName.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase) || projectFullName.EndsWith(".vcxproj", StringComparison.OrdinalIgnoreCase)))
{
await _package.LogAsync($"Found in input list {projectName}");
specifiedProjectsToIndexPath.Add(projectDir);
try
{
XDocument projDoc = XDocument.Load(projectFullName);
IEnumerable<string> compileItems;
if (projectFullName.EndsWith(".vcxproj", StringComparison.OrdinalIgnoreCase))
{
// Handle C++ project files
compileItems = projDoc.Descendants()
.Where(x => x.Name.LocalName == "ClCompile" || x.Name.LocalName == "ClInclude")
.Select(x => x.Attribute("Include")?.Value)
.Where(x => !string.IsNullOrEmpty(x));
}
else
{
// Handle C# project files
compileItems = projDoc.Descendants()
.Where(x => x.Name.LocalName == "Compile" || x.Name.LocalName == "Content")
.Select(x => x.Attribute("Include")?.Value)
.Where(x => !string.IsNullOrEmpty(x));
}

var fullPaths = new List<string>();
foreach (var item in compileItems)
{
string fullPath = Path.GetFullPath(Path.Combine(projectDir, item));
fullPaths.Add(fullPath);
}

if (fullPaths.Count > 0)
{
// Find the common root directory
string commonRoot = Path.GetDirectoryName(fullPaths[0]);
foreach (var path in fullPaths.Skip(1))
{
string directory = Path.GetDirectoryName(path);
while (!directory.StartsWith(commonRoot, StringComparison.OrdinalIgnoreCase) && commonRoot.Length > 3)
{
commonRoot = Path.GetDirectoryName(commonRoot);
}
}

await _package.LogAsync($"Common root directory: {commonRoot}");
if (Directory.Exists(commonRoot))
{
sourceDirectories.Add(commonRoot);
}
}
}
catch (Exception ex)
{
await _package.LogAsync($"Failed to parse project file {projectFullName}: {ex.Message}");
}
}
else if (openFilePaths.Count != 0)

if (openFilePaths.Count != 0)
{
string matchingFile = null;
List<string> matchingFiles = new List<string>();
foreach (var filePath in openFilePaths)
{
if (filePath.StartsWith(projectDir, StringComparison.OrdinalIgnoreCase))
if (sourceDirectories.Any(dir => filePath.StartsWith(dir, StringComparison.OrdinalIgnoreCase)))
{
await _package.LogAsync($"Found in open files {filePath}");
matchingFile = filePath;
break;
matchingFiles.Add(filePath);
}
}
if (!string.IsNullOrEmpty(matchingFile))
if (matchingFiles.Count > 0)
{
openFilesProjectsToIndexPath.Add(projectDir);
openFilePaths.Remove(matchingFile);
foreach (var dir in sourceDirectories)
{
openFilesProjectsToIndexPath.Add(dir);
}
foreach (var file in matchingFiles)
{
openFilePaths.Remove(file);
}
}
}
else
{
await _package.LogAsync($"Found in remaining {projectName}");
remainingProjectsToIndexPath.Add(projectDir);
foreach (var dir in sourceDirectories)
{
remainingProjectsToIndexPath.Add(dir);
}
}
processedProjects.Add(projectFullName);
}
Expand Down Expand Up @@ -875,14 +937,13 @@ async Task AddFilesToIndexLists(EnvDTE.Project project)
{
await AddFilesToIndexLists(project);
}
catch (Exception ex)
catch (Exception ex)
{
await _package.LogAsync($"Failed to process project: {ex.Message}");
continue;
}
}
List<string> result = new List<string>();
result.AddRange(specifiedProjectsToIndexPath);
result.AddRange(openFilesProjectsToIndexPath);
result.AddRange(remainingProjectsToIndexPath);
return result;
Expand Down
2 changes: 1 addition & 1 deletion CodeiumVS/SettingsPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class SettingsPage : DialogPage
private bool indexOpenFiles = true;

[Category("Codeium")]
[DisplayName("Enterprise Mode")]
[DisplayName("Self-Hosted Enterprise Mode")]
[Description(
"Set this to True if using Visual Studio with Codeium Enterprise. Requires restart.")]
public bool EnterpriseMode
Expand Down
2 changes: 1 addition & 1 deletion CodeiumVS/source.extension.vsixmanifest
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="Codeium.VisualStudio" Version="1.8.95" Language="en-US" Publisher="Codeium" />
<Identity Id="Codeium.VisualStudio" Version="1.8.96" Language="en-US" Publisher="Codeium" />
<DisplayName>Codeium</DisplayName>
<Description xml:space="preserve">The modern coding superpower: free AI code acceleration plugin for your favorite languages. Type less. Code more. Ship faster.</Description>
<MoreInfo>https://www.codeium.com</MoreInfo>
Expand Down

0 comments on commit a979eda

Please sign in to comment.