-
Notifications
You must be signed in to change notification settings - Fork 416
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #251 from OmniSharp/feature-highlighting
Feature highlighting
- Loading branch information
Showing
7 changed files
with
525 additions
and
1 deletion.
There are no files selected for viewing
108 changes: 108 additions & 0 deletions
108
src/OmniSharp/Api/v1/Highlighting/OmnisharpController.Highlighting.cs
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,108 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNet.Mvc; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Classification; | ||
using Microsoft.CodeAnalysis.Text; | ||
using OmniSharp.Models; | ||
|
||
namespace OmniSharp | ||
{ | ||
public partial class OmnisharpController | ||
{ | ||
[HttpPost("highlight")] | ||
public async Task<HighlightResponse> Highlight(HighlightRequest request) | ||
{ | ||
var documents = _workspace.GetDocuments(request.FileName); | ||
if (request.ProjectNames != null && request.ProjectNames.Length > 0) | ||
{ | ||
documents = documents.Where(d => request.ProjectNames.Contains(d.Project.Name, StringComparer.Ordinal)); | ||
} | ||
|
||
if (request.Classifications == null || request.Classifications.Length > 0) | ||
{ | ||
request.Classifications = AllClassifications; | ||
} | ||
|
||
if (request.ExcludeClassifications != null && request.ExcludeClassifications.Length > 0) | ||
{ | ||
request.Classifications = request.Classifications.Except(request.ExcludeClassifications).ToArray(); | ||
} | ||
|
||
var results = new List<ClassifiedResult>(); | ||
|
||
foreach (var document in documents) | ||
{ | ||
var project = document.Project.Name; | ||
var text = await document.GetTextAsync(); | ||
var spans = new List<ClassifiedSpan>(); | ||
|
||
if (request.Lines == null || request.Lines.Length == 0) | ||
{ | ||
foreach (var span in await Classifier.GetClassifiedSpansAsync(document, new TextSpan(0, text.Length))) | ||
{ | ||
spans.Add(span); | ||
} | ||
} | ||
else | ||
{ | ||
foreach (var line in request.Lines) | ||
{ | ||
foreach (var span in await Classifier.GetClassifiedSpansAsync(document, text.Lines[line - 1].Span)) | ||
{ | ||
spans.Add(span); | ||
} | ||
} | ||
} | ||
|
||
results.AddRange(FilterSpans(request.Classifications, spans) | ||
.Select(span => new ClassifiedResult() | ||
{ | ||
Span = span, | ||
Lines = text.Lines, | ||
Project = project | ||
})); | ||
} | ||
|
||
return new HighlightResponse() | ||
{ | ||
Highlights = results | ||
.GroupBy(result => result.Span.TextSpan.ToString()) | ||
.Select(grouping => HighlightSpan.FromClassifiedSpan(grouping.First().Span, grouping.First().Lines, grouping.Select(z => z.Project))) | ||
.ToArray() | ||
}; | ||
} | ||
|
||
class ClassifiedResult | ||
{ | ||
public ClassifiedSpan Span { get; set; } | ||
public TextLineCollection Lines { get; set; } | ||
public string Project { get; set; } | ||
} | ||
|
||
private HighlightClassification[] AllClassifications = Enum.GetValues(typeof(HighlightClassification)).Cast<HighlightClassification>().ToArray(); | ||
|
||
private IEnumerable<ClassifiedSpan> FilterSpans(HighlightClassification[] classifications, IEnumerable<ClassifiedSpan> spans) | ||
{ | ||
foreach (var classification in AllClassifications.Except(classifications)) | ||
{ | ||
if (classification == HighlightClassification.Name) | ||
spans = spans.Where(x => !x.ClassificationType.EndsWith(" name")); | ||
else if (classification == HighlightClassification.Comment) | ||
spans = spans.Where(x => x.ClassificationType != "comment" && !x.ClassificationType.StartsWith("xml doc comment ")); | ||
else if (classification == HighlightClassification.String) | ||
spans = spans.Where(x => x.ClassificationType != "string" && !x.ClassificationType.StartsWith("string ")); | ||
else if (classification == HighlightClassification.PreprocessorKeyword) | ||
spans = spans.Where(x => x.ClassificationType != "preprocessor keyword"); | ||
else if (classification == HighlightClassification.ExcludedCode) | ||
spans = spans.Where(x => x.ClassificationType != "excluded code"); | ||
else | ||
spans = spans.Where(x => x.ClassificationType != Enum.GetName(typeof(HighlightClassification), classification).ToLower()); | ||
} | ||
|
||
return spans; | ||
} | ||
} | ||
} |
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,94 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.CodeAnalysis.Classification; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace OmniSharp.Models | ||
{ | ||
public class HighlightSpan : IComparable<HighlightSpan> | ||
{ | ||
public int StartLine { get; set; } | ||
public int StartColumn { get; set; } | ||
public int EndLine { get; set; } | ||
public int EndColumn { get; set; } | ||
public string Kind { get; set; } | ||
public IEnumerable<string> Projects { get; set; } | ||
|
||
internal static HighlightSpan FromClassifiedSpan(ClassifiedSpan span, TextLineCollection lines, IEnumerable<string> projects) | ||
{ | ||
var linePos = lines.GetLinePositionSpan(span.TextSpan); | ||
|
||
return new HighlightSpan | ||
{ | ||
StartLine = linePos.Start.Line + 1, | ||
EndLine = linePos.End.Line + 1, | ||
StartColumn = linePos.Start.Character + 1, | ||
EndColumn = linePos.End.Character + 1, | ||
Kind = span.ClassificationType, | ||
Projects = projects | ||
}; | ||
} | ||
|
||
public int CompareTo(HighlightSpan other) | ||
{ | ||
if (other.StartLine < StartLine) | ||
{ | ||
return 1; | ||
} | ||
else if (other.StartLine > StartLine) | ||
{ | ||
return -1; | ||
} | ||
// same start line | ||
else if (other.StartColumn < StartColumn) | ||
{ | ||
return 1; | ||
} | ||
else if (other.StartColumn > StartColumn) | ||
{ | ||
return -1; | ||
} | ||
// same start line and start column | ||
else if (other.EndLine < EndLine) | ||
{ | ||
return 1; | ||
} | ||
else if (other.EndLine > EndLine) | ||
{ | ||
return -1; | ||
} | ||
// same start line, start column, and end line | ||
else if (other.EndColumn < EndColumn) | ||
{ | ||
return 1; | ||
} | ||
else if (other.EndColumn > EndColumn) | ||
{ | ||
return -1; | ||
} | ||
// same, same | ||
else | ||
{ | ||
return 0; | ||
} | ||
} | ||
|
||
public override bool Equals(object other) | ||
{ | ||
var node = other as FileMemberElement; | ||
return node != null | ||
&& node.Location.Line == StartLine | ||
&& node.Location.Column == StartColumn | ||
&& node.Location.EndLine == EndLine | ||
&& node.Location.EndColumn == EndColumn; | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return 13 * StartLine + | ||
17 * StartColumn + | ||
23 * EndLine + | ||
31 * EndColumn; | ||
} | ||
} | ||
} |
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,21 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.CodeAnalysis.Classification; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace OmniSharp.Models | ||
{ | ||
public enum HighlightClassification | ||
{ | ||
Name = 1, | ||
Comment = 2, | ||
String = 3, | ||
Operator = 4, | ||
Punctuation = 5, | ||
Keyword = 6, | ||
Number = 7, | ||
Identifier = 8, | ||
PreprocessorKeyword = 9, | ||
ExcludedCode = 10 | ||
} | ||
} |
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,25 @@ | ||
namespace OmniSharp.Models | ||
{ | ||
public class HighlightRequest : Request | ||
{ | ||
/// <summary> | ||
/// Specifies which lines to highlight. | ||
/// If none are given, highlight the entire | ||
/// file. | ||
/// </summary> | ||
public int[] Lines { get; set; } | ||
/// <summary> | ||
/// Specifies which projects to highlight for. | ||
// If none are given, highlight for all the projects. | ||
/// </summary> | ||
public string[] ProjectNames { get; set; } | ||
/// <summary> | ||
/// Request specific classifications, if none are requested you will get them all. | ||
/// </summary> | ||
public HighlightClassification[] Classifications { get; set; } | ||
/// <summary> | ||
/// Exclude specific classifications | ||
/// </summary> | ||
public HighlightClassification[] ExcludeClassifications { get; set; } | ||
} | ||
} |
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,7 @@ | ||
namespace OmniSharp.Models | ||
{ | ||
public class HighlightResponse | ||
{ | ||
public HighlightSpan[] Highlights { get; set; } | ||
} | ||
} |
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.