-
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
282 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
namespace CodeNav.Tests.Files | ||
{ | ||
public class Class2 | ||
{ | ||
#region R1 | ||
|
||
#region R15 | ||
public const int nestedRegionConstant = 1; | ||
|
||
#region R16 | ||
int i1 = 0; | ||
#endregion | ||
|
||
#endregion | ||
|
||
public void Test1() | ||
{ | ||
#region R11 | ||
int i1 = 0; | ||
#endregion | ||
|
||
#region R12 | ||
int i2 = 0; | ||
#endregion | ||
|
||
#region R13 | ||
int i3 = 0; | ||
#endregion | ||
|
||
#region R14 | ||
int i4 = 0; | ||
#endregion | ||
} | ||
|
||
public void Test2() | ||
{ | ||
|
||
} | ||
|
||
#endregion | ||
|
||
public void OutsideRegionFunction() | ||
{ | ||
|
||
} | ||
|
||
#region R2 | ||
public void SiblingRegionFunction() | ||
{ | ||
|
||
} | ||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using CodeNav.Mappers; | ||
using CodeNav.Models; | ||
using NUnit.Framework; | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
|
||
namespace CodeNav.Tests.MapperTests | ||
{ | ||
[TestFixture] | ||
public class RegionMapperTests | ||
{ | ||
[Test] | ||
public void TestRegions() | ||
{ | ||
var document = SyntaxMapper.MapDocument(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\Files\\TestRegions.cs")); | ||
|
||
Assert.IsTrue(document.Any()); | ||
|
||
// First item should be a namespace | ||
Assert.AreEqual(CodeItemKindEnum.Namespace, document.First().Kind); | ||
|
||
// There should be a single class | ||
var regionClass = (document.First() as IMembers).Members.First() as CodeClassItem; | ||
Assert.NotNull(regionClass); | ||
|
||
// The class should have a function in it | ||
Assert.NotNull(regionClass.Members.FirstOrDefault(m => m.Name.Equals("OutsideRegionFunction"))); | ||
|
||
// The class should have a region in it | ||
var regionR1 = regionClass.Members.FirstOrDefault(m => m.Name.Equals("#R1")) as CodeRegionItem; | ||
Assert.NotNull(regionR1); | ||
|
||
// Region R1 should have a nested region R15 with a constant in it | ||
var regionR15 = regionR1.Members.FirstOrDefault(m => m.Name.Equals("#R15")) as CodeRegionItem; | ||
Assert.NotNull(regionR15); | ||
Assert.NotNull(regionR15.Members.FirstOrDefault(m => m.Name.Equals("nestedRegionConstant"))); | ||
|
||
// Region R1 should have a function Test1 and Test2 in it | ||
Assert.NotNull(regionR1.Members.FirstOrDefault(m => m.Name.Equals("Test1"))); | ||
Assert.NotNull(regionR1.Members.FirstOrDefault(m => m.Name.Equals("Test2"))); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System.Windows.Media; | ||
|
||
namespace CodeNav.Helpers | ||
{ | ||
public static class ColorHelper | ||
{ | ||
public static SolidColorBrush CreateSolidColorBrush(Color color) | ||
{ | ||
var brush = new SolidColorBrush(color); | ||
brush.Freeze(); | ||
return brush; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
using CodeNav.Helpers; | ||
using CodeNav.Models; | ||
using CodeNav.Properties; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.Text; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Windows.Media; | ||
|
||
namespace CodeNav.Mappers | ||
{ | ||
public static class RegionMapper | ||
{ | ||
public static List<CodeRegionItem> MapRegions(SyntaxTree tree, TextSpan span) | ||
{ | ||
var root = tree.GetRoot(); | ||
var regionList = new List<CodeRegionItem>(); | ||
|
||
foreach (var regionDirective in root.DescendantTrivia().Where(i => i.Kind() == SyntaxKind.RegionDirectiveTrivia && span.Contains(i.Span))) | ||
{ | ||
regionList.Add(MapRegion(regionDirective)); | ||
} | ||
|
||
foreach (var endRegionDirective in root.DescendantTrivia().Where(j => j.Kind() == SyntaxKind.EndRegionDirectiveTrivia && span.Contains(j.Span))) | ||
{ | ||
var reg = regionList.Last(x => x.StartLine < GetStartLine(endRegionDirective) && x.EndLine == 0); | ||
reg.EndLine = GetEndLine(endRegionDirective); | ||
} | ||
|
||
var list = ToHierarchy(regionList, int.MinValue, int.MaxValue); | ||
|
||
return list.Select(r => r as CodeRegionItem).ToList(); | ||
} | ||
|
||
/// <summary> | ||
/// Transform the flat list of Regions to a nested List based on the start and end lines of the items | ||
/// </summary> | ||
/// <param name="regionList"></param> | ||
/// <param name="startLine"></param> | ||
/// <param name="endLine"></param> | ||
/// <returns></returns> | ||
private static List<CodeItem> ToHierarchy(List<CodeRegionItem> regionList, int startLine, int endLine) | ||
{ | ||
return (from r in regionList | ||
where r.StartLine > startLine && r.EndLine < endLine && | ||
!regionList.Any(q => IsContainedWithin(r, q) && (startLine != int.MinValue ? q.EndLine - q.StartLine < endLine - startLine : true)) | ||
select new CodeRegionItem | ||
{ | ||
Name = r.Name, | ||
FullName = r.Name, | ||
Id = r.Name, | ||
Tooltip = r.Name, | ||
StartLine = r.StartLine, | ||
EndLine = r.EndLine, | ||
Foreground = r.Foreground, | ||
BorderBrush = r.BorderBrush, | ||
FontSize = r.FontSize, | ||
Kind = r.Kind, | ||
Members = ToHierarchy(regionList, r.StartLine, r.EndLine) | ||
}).ToList<CodeItem>(); | ||
} | ||
|
||
private static CodeRegionItem MapRegion(SyntaxTrivia source) | ||
{ | ||
var name = "#" + source.ToString().Replace("#region ", string.Empty); | ||
return new CodeRegionItem | ||
{ | ||
Name = name, | ||
FullName = name, | ||
Id = name, | ||
Tooltip = name, | ||
StartLine = GetStartLine(source), | ||
Foreground = ColorHelper.CreateSolidColorBrush(Colors.Black), | ||
BorderBrush = ColorHelper.CreateSolidColorBrush(Colors.DarkGray), | ||
FontSize = Settings.Default.Font.SizeInPoints - 2, | ||
Kind = CodeItemKindEnum.Region | ||
}; | ||
} | ||
|
||
/// <summary> | ||
/// Add a CodeItem to the list of Regions, will recursively find the right region to add the item | ||
/// </summary> | ||
/// <param name="regions"></param> | ||
/// <param name="item"></param> | ||
/// <returns></returns> | ||
public static bool AddToRegion(List<CodeRegionItem> regions, CodeItem item) | ||
{ | ||
if (item?.StartLine == null) return false; | ||
|
||
foreach (var region in regions) | ||
{ | ||
if (region.Kind == CodeItemKindEnum.Region) | ||
{ | ||
if (AddToRegion(region.Members, item)) | ||
{ | ||
return true; | ||
} | ||
|
||
if (item.StartLine >= region.StartLine && item.StartLine <= region.EndLine) | ||
{ | ||
region.Members.Add(item); | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/// <summary> | ||
/// Help add a CodeItem to a inner Region structure | ||
/// </summary> | ||
/// <param name="members"></param> | ||
/// <param name="item"></param> | ||
/// <returns></returns> | ||
private static bool AddToRegion(List<CodeItem> members, CodeItem item) | ||
{ | ||
foreach (var member in members) | ||
{ | ||
if (member is IMembers && AddToRegion((member as IMembers).Members, item)) | ||
{ | ||
return true; | ||
} | ||
|
||
if (member.Kind == CodeItemKindEnum.Region && IsContainedWithin(item, member)) | ||
{ | ||
(member as CodeRegionItem).Members.Add(item); | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private static int GetStartLine(SyntaxTrivia source) => | ||
source.SyntaxTree.GetLineSpan(source.Span).StartLinePosition.Line + 1; | ||
|
||
private static int GetEndLine(SyntaxTrivia source) => | ||
source.SyntaxTree.GetLineSpan(source.Span).EndLinePosition.Line + 1; | ||
|
||
/// <summary> | ||
/// Check if item 1 is contained within item 2 | ||
/// </summary> | ||
/// <param name="r1">Smaller Item</param> | ||
/// <param name="r2">Bigger Item</param> | ||
/// <returns></returns> | ||
private static bool IsContainedWithin(CodeItem r1, CodeItem r2) => | ||
r1.StartLine > r2.StartLine && r1.EndLine < r2.EndLine; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.