Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ permissions:
contents: read

env:
version: '10.10.${{ github.run_number }}'
version: '10.11.${{ github.run_number }}'
dotnetVersion: '8'
repoUrl: ${{ github.server_url }}/${{ github.repository }}
vsixPath: src/CodeNav/bin/Release/net472/CodeNav.vsix
Expand Down Expand Up @@ -142,20 +142,20 @@ jobs:
uses: actions/download-artifact@v8

- name: Publish to Marketplace
uses: cezarypiatek/VsixPublisherAction@1.2
uses: madskristensen/publish-marketplace@v2
with:
extension-file: ${{ github.workspace }}/CodeNav/${{ env.vsixPath }}
publish-manifest-file: CodeNav/publish-manifest.json
personal-access-code: ${{ secrets.VS_PUBLISHER_ACCESS_TOKEN }}

- name: Publish to Marketplace 2022
uses: cezarypiatek/VsixPublisherAction@1.2
uses: madskristensen/publish-marketplace@v2
with:
extension-file: ${{ github.workspace }}/CodeNav2022/${{ env.vsixPath }}
publish-manifest-file: CodeNav2022/publish-manifest-2022.json
personal-access-code: ${{ secrets.VS_PUBLISHER_ACCESS_TOKEN }}

- name: Publish to Open VSIX Gallery
uses: timheuer/openvsixpublish@v1
uses: madskristensen/publish-vsixgallery@v1
with:
vsix-file: ${{ github.workspace }}/CodeNav/${{ env.vsixPath }}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Visual Studio extension to show the code structure of your current document

# 🔤 Language support
- C#
- Visual Basic (enable it in the CodeNav settings)

# ⬇️ Installing
[Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=SamirBoulema.CodeNav2026)
Expand Down Expand Up @@ -60,4 +61,4 @@ The CodeNav tool window can be opened via the entry in the `Extensions` menu.
![Compact](https://raw.githubusercontent.com/sboulema/CodeNav/main/art/Compact.png)

# 📄 Documentation
Looking for more info? Read the full [Documentation](https://github.com/sboulema/CodeNav/blob/main/docs/index.md) with links, guides, troubleshooting, and tips.
Looking for more info? Read the full [Documentation](https://github.com/sboulema/CodeNav/blob/main/docs/index.md) with links, guides, troubleshooting, and tips.
3 changes: 2 additions & 1 deletion src/CodeNav.OutOfProc/CodeNav.OutOfProc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

<ItemGroup>
<PackageReference Include="DebounceThrottle" Version="3.0.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="5.3.0" />
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.14.40608" PrivateAssets="all" />
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.14.40608" PrivateAssets="all" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@
</StackPanel>
</GroupBox>

<GroupBox
Header="Languages"
Margin="5"
Padding="5">
<StackPanel>
<CheckBox IsChecked="{Binding EnableCSharp, Mode=TwoWay}">
C#
</CheckBox>

<CheckBox IsChecked="{Binding EnableVisualBasic, Mode=TwoWay}">
Visual Basic
</CheckBox>
</StackPanel>
</GroupBox>

<GroupBox
Header="Performance"
Margin="5"
Expand Down Expand Up @@ -75,4 +90,4 @@
</GroupBox>
</StackPanel>

</DataTemplate>
</DataTemplate>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
using CodeNav.OutOfProc.Constants;
using System.Runtime.Serialization;

namespace CodeNav.OutOfProc.Dialogs.SettingsDialog;

Expand Down Expand Up @@ -52,4 +53,16 @@ public class SettingsDialogData
/// </summary>
[DataMember]
public bool UseCompactMode { get; set; }

/// <summary>
/// Setting which languages are enabled for CodeNav.
/// </summary>
[DataMember]
public bool EnableCSharp { get; set; } = true;

/// <summary>
/// Setting which languages are enabled for CodeNav.
/// </summary>
[DataMember]
public bool EnableVisualBasic { get; set; } = false;
}
19 changes: 19 additions & 0 deletions src/CodeNav.OutOfProc/Interfaces/IDocumentMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using CodeNav.OutOfProc.Models;
using CodeNav.OutOfProc.ViewModels;
using Microsoft.VisualStudio.Extensibility;

namespace CodeNav.OutOfProc.Interfaces;

public interface IDocumentMapper
{
bool CanMapDocument(
string filePath,
GlobalSettings settings);

Task<List<CodeItem>> MapDocument(
string text,
string? excludeFilePath,
CodeDocumentViewModel codeDocumentViewModel,
VisualStudioExtensibility extensibility,
CancellationToken cancellationToken);
}
13 changes: 9 additions & 4 deletions src/CodeNav.OutOfProc/Languages/CSharp/Mappers/DocumentMapper.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using CodeNav.OutOfProc.Interfaces;
using CodeNav.OutOfProc.Models;
using CodeNav.OutOfProc.ViewModels;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -7,7 +9,7 @@

namespace CodeNav.OutOfProc.Languages.CSharp.Mappers;

public class DocumentMapper
public class DocumentMapper : IDocumentMapper
{
/// <summary>
/// Map text document to list of code items.
Expand All @@ -18,7 +20,7 @@ public class DocumentMapper
/// <param name="extensibility">Visual Studio extensibility used to retrieve all solution files for compilation</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>List of code items</returns>
public static async Task<List<CodeItem>> MapDocument(
public async Task<List<CodeItem>> MapDocument(
string text,
string? excludeFilePath,
CodeDocumentViewModel codeDocumentViewModel,
Expand Down Expand Up @@ -138,6 +140,9 @@ SyntaxKind.ExtensionBlockDeclaration when member is ExtensionBlockDeclarationSyn
_ => null,
};

public static bool CanMapDocument(string filePath)
=> filePath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase);
public bool CanMapDocument(
string filePath,
GlobalSettings settings)
=> settings.EnableCSharp &&
filePath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Drawing;

namespace CodeNav.OutOfProc.Languages.CSharp.Mappers;

Expand Down
166 changes: 166 additions & 0 deletions src/CodeNav.OutOfProc/Languages/VisualBasic/Mappers/BaseMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
using CodeNav.OutOfProc.Constants;
using CodeNav.OutOfProc.ViewModels;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;

namespace CodeNav.OutOfProc.Languages.VisualBasic.Mappers;

public static class BaseMapper
{
public static T MapBase<T>(
SyntaxNode source,
SemanticModel semanticModel,
CodeDocumentViewModel codeDocumentViewModel,
SyntaxToken? identifier = null,
NameSyntax? nameSyntax = null,
string name = "",
SyntaxTokenList? modifiers = null) where T : CodeItem
{
var codeItem = Activator.CreateInstance<T>();

var codeItemName = MapName(identifier, nameSyntax, name);

codeItem.Name = codeItemName;
codeItem.FullName = MapFullName(
source,
codeItemName,
semanticModel);

codeItem.FilePath =
string.IsNullOrEmpty(source.SyntaxTree.FilePath)
? null
: new Uri(source.SyntaxTree.FilePath);

codeItem.Id = codeItem.FullName;
codeItem.Tooltip = codeItemName;
codeItem.Access = MapAccess(modifiers, source);
codeItem.CodeDocumentViewModel = codeDocumentViewModel;

codeItem.Span = source.Span;
codeItem.IdentifierSpan = identifier?.Span;
codeItem.OutlineSpan = MapOutlineSpan(
codeItem.Span,
codeItem.IdentifierSpan,
nameSyntax?.Span);

return codeItem;
}

private static TextSpan MapOutlineSpan(
TextSpan span,
TextSpan? identifierSpan,
TextSpan? nameSpan)
{
var outlineSpanStart = 0;

if (nameSpan != null)
{
outlineSpanStart = nameSpan.Value.End;
}

if (identifierSpan != null)
{
outlineSpanStart = identifierSpan.Value.End;
}

return new TextSpan(
outlineSpanStart,
span.End - outlineSpanStart);
}

private static string MapFullName(
SyntaxNode source,
string name,
SemanticModel semanticModel)
{
try
{
var symbol = semanticModel.GetDeclaredSymbol(source);

return symbol?.ToString() ?? name;
}
catch (Exception)
{
return name;
}
}

private static string MapName(
SyntaxToken? identifier,
NameSyntax? nameSyntax,
string name = "")
{
if (identifier != null &&
!identifier.Value.IsKind(SyntaxKind.None))
{
return identifier.Value.Text;
}

if (nameSyntax != null)
{
return nameSyntax.ToString();
}

return name;
}

private static CodeItemAccessEnum MapAccess(
SyntaxTokenList? modifiers,
SyntaxNode source)
{
if (modifiers == null)
{
return MapDefaultAccess(source);
}

if (modifiers.Value.Any(m =>
m.IsKind(SyntaxKind.PublicKeyword)))
{
return CodeItemAccessEnum.Public;
}

if (modifiers.Value.Any(m =>
m.IsKind(SyntaxKind.PrivateKeyword)))
{
return CodeItemAccessEnum.Private;
}

if (modifiers.Value.Any(m =>
m.IsKind(SyntaxKind.ProtectedKeyword)))
{
return CodeItemAccessEnum.Protected;
}

if (modifiers.Value.Any(m =>
m.IsKind(SyntaxKind.FriendKeyword)))
{
return CodeItemAccessEnum.Internal;
}

return MapDefaultAccess(source);
}

private static CodeItemAccessEnum MapDefaultAccess(
SyntaxNode source)
{
if (source.Parent is CompilationUnitSyntax)
{
return source switch
{
EnumBlockSyntax => CodeItemAccessEnum.Public,
NamespaceBlockSyntax => CodeItemAccessEnum.Public,
_ => CodeItemAccessEnum.Internal,
};
}

return source switch
{
NamespaceBlockSyntax => CodeItemAccessEnum.Public,
EnumBlockSyntax => CodeItemAccessEnum.Public,
InterfaceBlockSyntax => CodeItemAccessEnum.Public,
_ => CodeItemAccessEnum.Private,
};
}
}
Loading
Loading