diff options
author | Lluis Sanchez <llsan@microsoft.com> | 2018-05-25 19:21:35 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-25 19:21:35 +0300 |
commit | f7b338b596748ffa52b2f86a292bb52a1ce2a4fd (patch) | |
tree | 69f4e002f046aa3b2444ed6cd4ba02a018f9fbbf | |
parent | 6f05bc6453f03e6401525e16341b244bbe34ed8c (diff) | |
parent | 7b736c39bbd344cc45d915790b79a07bbd9c2d25 (diff) |
Merge pull request #4842 from mono/fix4822monodevelop-7.6.0.947
Fix #4822: Toggle line comment menu no longer exists
3 files changed, 383 insertions, 345 deletions
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/VSEditor/TagBasedSyntaxHighlighting.cs b/main/src/addins/MonoDevelop.SourceEditor2/VSEditor/TagBasedSyntaxHighlighting.cs index ea97a58c27..b479ef5883 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/VSEditor/TagBasedSyntaxHighlighting.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/VSEditor/TagBasedSyntaxHighlighting.cs @@ -1,7 +1,7 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// +//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+//
using System;
using System.Linq;
using System.Collections.Generic;
@@ -24,353 +24,361 @@ using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Text.Editor;
-using static Microsoft.VisualStudio.Language.Intellisense.Implementation.MDUtils; -using Microsoft.VisualStudio.Language.StandardClassification; -using MonoDevelop.Ide.Tasks; - +using static Microsoft.VisualStudio.Language.Intellisense.Implementation.MDUtils;
+using Microsoft.VisualStudio.Language.StandardClassification;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Tasks;
+
namespace Microsoft.VisualStudio.Platform
-{ - [Export (typeof (ITagBasedSyntaxHighlightingFactory))] - internal sealed class TagBasedSyntaxHighlightingFactory : ITagBasedSyntaxHighlightingFactory - { - public ISyntaxHighlighting CreateSyntaxHighlighting (ITextView textView) - { - return new TagBasedSyntaxHighlighting (textView, null); - } - - public ISyntaxHighlighting CreateSyntaxHighlighting (ITextView textView, string defaultScope) - { - return new TagBasedSyntaxHighlighting (textView, defaultScope); - } - } - - internal sealed class TagBasedSyntaxHighlighting : ISyntaxHighlighting - { +{
+ [Export (typeof (ITagBasedSyntaxHighlightingFactory))]
+ internal sealed class TagBasedSyntaxHighlightingFactory : ITagBasedSyntaxHighlightingFactory
+ {
+ public ISyntaxHighlighting CreateSyntaxHighlighting (ITextView textView)
+ {
+ return new TagBasedSyntaxHighlighting (textView, null);
+ }
+
+ public ISyntaxHighlighting CreateSyntaxHighlighting (ITextView textView, string defaultScope)
+ {
+ return new TagBasedSyntaxHighlighting (textView, defaultScope);
+ }
+ }
+
+ internal sealed class TagBasedSyntaxHighlighting : ISyntaxHighlighting
+ {
private ITextView textView { get; }
private IAccurateClassifier classifier { get; set; }
- readonly Dictionary<string, ScopeStack> classificationMap; - private MonoDevelop.Ide.Editor.ITextDocument textDocument { get; } - - internal TagBasedSyntaxHighlighting (ITextView textView, string defaultScope) - { - this.textView = textView; - this.textDocument = textView.GetTextEditor (); + readonly Dictionary<string, ScopeStack> classificationMap;
+ private MonoDevelop.Ide.Editor.ITextDocument textDocument { get; }
+
+ internal TagBasedSyntaxHighlighting (ITextView textView, string defaultScope)
+ {
+ this.textView = textView;
+ this.textDocument = textView.GetTextEditor ();
if (defaultScope != null)
classificationMap = GetClassificationMap (defaultScope);
}
- - public Task<HighlightedLine> GetHighlightedLineAsync (IDocumentLine line, CancellationToken cancellationToken) - { - ITextSnapshotLine snapshotLine = (line as Mono.TextEditor.TextDocument.DocumentLineFromTextSnapshotLine)?.Line; - if ((this.classifier == null) || (snapshotLine == null)) { - return Task.FromResult (new HighlightedLine (line, new [] { new ColoredSegment (0, line.Length, ScopeStack.Empty) })); - } - List<ColoredSegment> coloredSegments = new List<ColoredSegment> (); - - SnapshotSpan snapshotSpan = new SnapshotSpan(textView.TextBuffer.CurrentSnapshot, snapshotLine.Extent.Span); - int start = snapshotSpan.Start.Position; - int end = snapshotSpan.End.Position; - - IList<ClassificationSpan> classifications = this.classifier.GetClassificationSpans (snapshotSpan); - - int lastClassifiedOffsetEnd = start; +
+ public Task<HighlightedLine> GetHighlightedLineAsync (IDocumentLine line, CancellationToken cancellationToken)
+ {
+ ITextSnapshotLine snapshotLine = (line as Mono.TextEditor.TextDocument.DocumentLineFromTextSnapshotLine)?.Line;
+ if ((this.classifier == null) || (snapshotLine == null)) {
+ return Task.FromResult (new HighlightedLine (line, new [] { new ColoredSegment (0, line.Length, ScopeStack.Empty) }));
+ }
+ List<ColoredSegment> coloredSegments = new List<ColoredSegment> ();
+
+ SnapshotSpan snapshotSpan = new SnapshotSpan(textView.TextBuffer.CurrentSnapshot, snapshotLine.Extent.Span);
+ int start = snapshotSpan.Start.Position;
+ int end = snapshotSpan.End.Position;
+
+ IList<ClassificationSpan> classifications = this.classifier.GetClassificationSpans (snapshotSpan);
+
+ int lastClassifiedOffsetEnd = start;
ScopeStack scopeStack;
- foreach (ClassificationSpan curSpan in classifications) { - if (curSpan.Span.Start > lastClassifiedOffsetEnd) { - scopeStack = new ScopeStack (EditorThemeColors.Foreground); - ColoredSegment whitespaceSegment = new ColoredSegment (lastClassifiedOffsetEnd - start, curSpan.Span.Start - lastClassifiedOffsetEnd, scopeStack); - coloredSegments.Add (whitespaceSegment); + foreach (ClassificationSpan curSpan in classifications) {
+ if (curSpan.Span.Start > lastClassifiedOffsetEnd) {
+ scopeStack = new ScopeStack (EditorThemeColors.Foreground);
+ ColoredSegment whitespaceSegment = new ColoredSegment (lastClassifiedOffsetEnd - start, curSpan.Span.Start - lastClassifiedOffsetEnd, scopeStack);
+ coloredSegments.Add (whitespaceSegment);
+ }
+
+ scopeStack = GetScopeStackFromClassificationType (curSpan.ClassificationType);
+ if (scopeStack.Peek ().StartsWith ("comment", StringComparison.Ordinal)) {
+ ScanAndAddComment (coloredSegments, start, scopeStack, curSpan);
+ } else {
+ var curColoredSegment = new ColoredSegment (curSpan.Span.Start - start, curSpan.Span.Length, scopeStack);
+ coloredSegments.Add (curColoredSegment);
+ }
+
+ lastClassifiedOffsetEnd = curSpan.Span.End;
+ }
+
+ if (end > lastClassifiedOffsetEnd) {
+ scopeStack = new ScopeStack (EditorThemeColors.Foreground);
+ ColoredSegment whitespaceSegment = new ColoredSegment (lastClassifiedOffsetEnd - start, end - lastClassifiedOffsetEnd, scopeStack);
+ coloredSegments.Add (whitespaceSegment);
+ }
+
+ return Task.FromResult(new HighlightedLine (line, coloredSegments));
+ }
+ #region Tag Comment Scanning
+
+ void ScanAndAddComment (List<ColoredSegment> coloredSegments, int startOffset, ScopeStack commentScopeStack, ClassificationSpan classificationSpan)
+ {
+ int lastClassifiedOffset = classificationSpan.Span.Start;
+ try {
+ // Scan comments for tag highlighting
+ var text = textView.TextSnapshot.GetText (classificationSpan.Span);
+ int idx = 0, oldIdx = 0;
+
+ while ((idx = FindNextCommentTagIndex (text, idx, out string commentTag)) >= 0) {
+ var headSpanLength = idx - oldIdx;
+ if (headSpanLength > 0) {
+ var headSegment = new ColoredSegment (lastClassifiedOffset - startOffset, headSpanLength, commentScopeStack);
+ lastClassifiedOffset += headSpanLength;
+ coloredSegments.Add (headSegment);
+ }
+ var highlightSegment = new ColoredSegment (lastClassifiedOffset - startOffset, commentTag.Length, commentScopeStack.Push ("markup.other"));
+ coloredSegments.Add (highlightSegment);
+ idx += commentTag.Length;
+ lastClassifiedOffset += commentTag.Length;
+ oldIdx = idx;
+ }
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while scanning comment tags.", e);
+ }
+ int tailSpanLength = classificationSpan.Span.End - lastClassifiedOffset;
+ if (tailSpanLength > 0) {
+ var tailSpan = new ColoredSegment (lastClassifiedOffset - startOffset, tailSpanLength, commentScopeStack);
+ coloredSegments.Add (tailSpan);
+ }
+ }
+
+ static int FindNextCommentTagIndex (string text, int startIndex, out string commentTag)
+ {
+ var foundIndex = -1;
+ commentTag = null;
+ foreach (var tag in CommentTag.SpecialCommentTags) {
+ var i = text.IndexOf (tag.Tag, startIndex, StringComparison.OrdinalIgnoreCase);
+ if (i < 0)
+ continue;
+ if (i < foundIndex || foundIndex < 0) {
+ foundIndex = i;
+ commentTag = tag.Tag;
+ }
+ }
+ return foundIndex;
+ }
+
+ #endregion
+
+ public async Task<ScopeStack> GetScopeStackAsync (int offset, CancellationToken cancellationToken)
+ {
+ var line = textDocument.GetLineByOffset (offset);
+ var highligthedLine = await GetHighlightedLineAsync (line, cancellationToken).ConfigureAwait (false);
+ offset -= line.Offset;
+ foreach (var segment in highligthedLine.Segments) {
+ if (segment.Offset <= offset && segment.EndOffset >= offset)
+ return segment.ScopeStack;
+ }
+ return ScopeStack.Empty;
+ }
+
+ private EventHandler<LineEventArgs> _highlightingStateChanged;
+ public event EventHandler<LineEventArgs> HighlightingStateChanged {
+ add {
+ lock (this) {
+ _highlightingStateChanged += value;
}
- scopeStack = GetScopeStackFromClassificationType (curSpan.ClassificationType); - if (scopeStack.Peek ().StartsWith ("comment", StringComparison.Ordinal)) { - ScanAndAddComment (coloredSegments, start, scopeStack, curSpan); - } else { - var curColoredSegment = new ColoredSegment (curSpan.Span.Start - start, curSpan.Span.Length, scopeStack); - coloredSegments.Add (curColoredSegment); - } - - lastClassifiedOffsetEnd = curSpan.Span.End; - } - - if (end > lastClassifiedOffsetEnd) { - scopeStack = new ScopeStack (EditorThemeColors.Foreground); - ColoredSegment whitespaceSegment = new ColoredSegment (lastClassifiedOffsetEnd - start, end - lastClassifiedOffsetEnd, scopeStack); - coloredSegments.Add (whitespaceSegment); - } - - return Task.FromResult(new HighlightedLine (line, coloredSegments)); - } - #region Tag Comment Scanning - - void ScanAndAddComment (List<ColoredSegment> coloredSegments, int startOffset, ScopeStack commentScopeStack, ClassificationSpan classificationSpan) - { - int lastClassifiedOffset = classificationSpan.Span.Start; - try { - // Scan comments for tag highlighting - var text = textView.TextSnapshot.GetText (classificationSpan.Span); - int idx = 0, oldIdx = 0; - - while ((idx = FindNextCommentTagIndex (text, idx, out string commentTag)) >= 0) { - var headSpanLength = idx - oldIdx; - if (headSpanLength > 0) { - var headSegment = new ColoredSegment (lastClassifiedOffset - startOffset, headSpanLength, commentScopeStack); - lastClassifiedOffset += headSpanLength; - coloredSegments.Add (headSegment); - } - var highlightSegment = new ColoredSegment (lastClassifiedOffset - startOffset, commentTag.Length, commentScopeStack.Push ("markup.other")); - coloredSegments.Add (highlightSegment); - idx += commentTag.Length; - lastClassifiedOffset += commentTag.Length; - oldIdx = idx; - } - } catch (Exception e) { - LoggingService.LogError ("Error while scanning comment tags.", e); - } - int tailSpanLength = classificationSpan.Span.End - lastClassifiedOffset; - if (tailSpanLength > 0) { - var tailSpan = new ColoredSegment (lastClassifiedOffset - startOffset, tailSpanLength, commentScopeStack); - coloredSegments.Add (tailSpan); - } - } - - static int FindNextCommentTagIndex (string text, int startIndex, out string commentTag) - { - var foundIndex = -1; - commentTag = null; - foreach (var tag in CommentTag.SpecialCommentTags) { - var i = text.IndexOf (tag.Tag, startIndex, StringComparison.OrdinalIgnoreCase); - if (i < 0) - continue; - if (i < foundIndex || foundIndex < 0) { - foundIndex = i; - commentTag = tag.Tag; - } - } - return foundIndex; - } - - #endregion - - public Task<ScopeStack> GetScopeStackAsync (int offset, CancellationToken cancellationToken) - { - return Task.FromResult (ScopeStack.Empty); - } - - private EventHandler<LineEventArgs> _highlightingStateChanged; - public event EventHandler<LineEventArgs> HighlightingStateChanged { - add { - lock (this) { - _highlightingStateChanged += value; - } - if (this.classifier == null) {
- this.classifier = PlatformCatalog.Instance.ViewClassifierAggregatorService.GetClassifier (this.textView) as IAccurateClassifier; - this.classifier.ClassificationChanged += this.OnClassificationChanged; - } - } - - remove { - bool dispose = false; - lock (this) { - _highlightingStateChanged -= value; - dispose = _highlightingStateChanged == null; - } - - if (dispose && (this.classifier != null)) { - this.classifier.ClassificationChanged -= this.OnClassificationChanged; - (this.classifier as IDisposable)?.Dispose (); - this.classifier = null; - } - } - } - - private void OnClassificationChanged (object sender, ClassificationChangedEventArgs args) - { - var handler = _highlightingStateChanged; - if (handler != null) { - foreach (Mono.TextEditor.MdTextViewLineCollection.MdTextViewLine line in textView.TextViewLines) { - if (line.Start.Position > args.ChangeSpan.End.Position || line.End.Position < args.ChangeSpan.Start) - continue; - var oldSegments = line.layoutWrapper.HighlightedLine.Segments; - var newSegments = GetHighlightedLineAsync (line.line, CancellationToken.None).Result.Segments; - if (oldSegments.Count != newSegments.Count) { - handler (this, new LineEventArgs (line.line)); - continue; - } - for (int i = 0; i < oldSegments.Count; i++) { - if (newSegments [i].ColorStyleKey != oldSegments [i].ColorStyleKey) { - handler (this, new LineEventArgs (line.line)); - break; - } - } - } - } + this.classifier = PlatformCatalog.Instance.ViewClassifierAggregatorService.GetClassifier (this.textView) as IAccurateClassifier;
+ this.classifier.ClassificationChanged += this.OnClassificationChanged;
+ }
+ }
+
+ remove {
+ bool dispose = false;
+ lock (this) {
+ _highlightingStateChanged -= value;
+ dispose = _highlightingStateChanged == null;
+ }
+
+ if (dispose && (this.classifier != null)) {
+ this.classifier.ClassificationChanged -= this.OnClassificationChanged;
+ (this.classifier as IDisposable)?.Dispose ();
+ this.classifier = null;
+ }
+ }
}
- - Dictionary<IClassificationType, ScopeStack> classificationTypeToScopeCache = new Dictionary<IClassificationType, ScopeStack> (); - static ScopeStack defaultScopeStack = new ScopeStack (EditorThemeColors.Foreground); -
- private ScopeStack GetScopeStackFromClassificationType (IClassificationType classificationType) - { - if (classificationTypeToScopeCache.TryGetValue (classificationType, out var cachedScope)) - return cachedScope; - ScopeStack scope = null; - void ProcessClassificationType(IClassificationType classification) - { - foreach (var baseType in classification.BaseTypes) { - ProcessClassificationType (baseType); - } - //This comparision with Identifier and Keyword is very hacky - //what we are doing here is, making sure anything has greater priorty over - //this two Identifer/Keyword, I came to this two from - //https://github.com/dotnet/roslyn/blob/88d1bd1/src/EditorFeatures/Core.Wpf/Classification/ClassificationTypeFormatDefinitions.cs - //Which orders different classifications by priority... - //This is needed so Semantical classification for Interface or Class is greater then Identifier from Syntactical classifeer - if (scope != null && (classification.Classification == PredefinedClassificationTypeNames.Identifier || classification.Classification == PredefinedClassificationTypeNames.Keyword)) - return; - if (classificationMap != null && classificationMap.TryGetValue (classification.Classification, out var mappedScope)) { - scope = mappedScope; - return; - } - var styleName = GetStyleNameFromClassificationName (classification.Classification); - if (styleName == null) - return; - scope = new ScopeStack (styleName); - } - ProcessClassificationType (classificationType); +
+ private void OnClassificationChanged (object sender, ClassificationChangedEventArgs args)
+ {
+ var handler = _highlightingStateChanged;
+ if (handler != null) {
+ foreach (Mono.TextEditor.MdTextViewLineCollection.MdTextViewLine line in textView.TextViewLines) {
+ if (line.Start.Position > args.ChangeSpan.End.Position || line.End.Position < args.ChangeSpan.Start)
+ continue;
+ var oldSegments = line.layoutWrapper.HighlightedLine.Segments;
+ var newSegments = GetHighlightedLineAsync (line.line, CancellationToken.None).Result.Segments;
+ if (oldSegments.Count != newSegments.Count) {
+ handler (this, new LineEventArgs (line.line));
+ continue;
+ }
+ for (int i = 0; i < oldSegments.Count; i++) {
+ if (newSegments [i].ColorStyleKey != oldSegments [i].ColorStyleKey) {
+ handler (this, new LineEventArgs (line.line));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ Dictionary<IClassificationType, ScopeStack> classificationTypeToScopeCache = new Dictionary<IClassificationType, ScopeStack> ();
+ static ScopeStack defaultScopeStack = new ScopeStack (EditorThemeColors.Foreground);
+
+ private ScopeStack GetScopeStackFromClassificationType (IClassificationType classificationType)
+ {
+ if (classificationTypeToScopeCache.TryGetValue (classificationType, out var cachedScope))
+ return cachedScope;
+ ScopeStack scope = null;
+ void ProcessClassificationType(IClassificationType classification)
+ {
+ foreach (var baseType in classification.BaseTypes) {
+ ProcessClassificationType (baseType);
+ }
+ //This comparision with Identifier and Keyword is very hacky
+ //what we are doing here is, making sure anything has greater priorty over
+ //this two Identifer/Keyword, I came to this two from
+ //https://github.com/dotnet/roslyn/blob/88d1bd1/src/EditorFeatures/Core.Wpf/Classification/ClassificationTypeFormatDefinitions.cs
+ //Which orders different classifications by priority...
+ //This is needed so Semantical classification for Interface or Class is greater then Identifier from Syntactical classifeer
+ if (scope != null && (classification.Classification == PredefinedClassificationTypeNames.Identifier || classification.Classification == PredefinedClassificationTypeNames.Keyword))
+ return;
+ if (classificationMap != null && classificationMap.TryGetValue (classification.Classification, out var mappedScope)) {
+ scope = mappedScope;
+ return;
+ }
+ var styleName = GetStyleNameFromClassificationName (classification.Classification);
+ if (styleName == null)
+ return;
+ scope = new ScopeStack (styleName);
+ }
+ ProcessClassificationType (classificationType);
return classificationTypeToScopeCache [classificationType] = scope ?? defaultScopeStack;
- } - - private string GetStyleNameFromClassificationName (string classificationName) - { - string styleName = null; - - // MONO: TODO: get this from the EditorFormat? - switch (classificationName) { - // MONO: TODO: Make each language MEF export this knowledge? - - // CSS Entries - case "CSS Comment": - styleName = "comment.block.css"; - break; - case "CSS Keyword": - styleName = "keyword.other.css"; - break; - case "CSS Selector": - styleName = "entity.name.tag.css"; - break; - case "CSS Property Name": - styleName = "support.type.property-name.css"; - break; - case "CSS Property Value": - styleName = "support.constant.property-value.css"; - break; - case "CSS String Value": - styleName = "string.quoted.double.css"; - break; - - // HTML Entries - case "HTML Attribute Name": - styleName = "entity.other.attribute-name.html"; - break; - case "HTML Attribute Value": - styleName = "string.unquoted.html"; - break; - case "HTML Comment": - styleName = "comment.block.html"; - break; - case "HTML Element Name": - styleName = "entity.name.tag.html"; - break; - case "HTML Entity": - styleName = "constant.character.entity.html"; - break; - case "HTML Operator": - styleName = "punctuation.separator.key-value.html"; - break; - case "HTML Server-Side Script": - //styleName = "punctuation.section.embedded.begin"; // suggested by mike, does nothing - //styleName = "punctuation.section.embedded.begin.cs"; // suggested by mike, does nothing - styleName = "meta.preprocessor.source.cs"; // TODO: Find a name to use here - //styleName = style.HtmlServerSideScript.Name; - break; - case "HTML Tag Delimiter": - styleName = "punctuation.definition.tag.begin.html"; - break; - case "RazorCode": - //styleName = style.RazorCode.Name; - break; - case "RazorTagHelperAttribute": - styleName = "markup.bold"; - break; - case "RazorTagHelperElement": - styleName = "markup.bold"; - break; - - // JSON Entries - case "operator": - styleName = "meta.structure.dictionary.value.json"; - break; - case "string": - styleName = "string.quoted.double.json"; - break; - case "keyword": - styleName = "constant.language.json"; - break; - case "number": - styleName = "constant.numeric.json"; - break; - case "comment": - styleName = "comment.block.json"; - break; - case "JSON Property Name": - styleName = "support.type.property-name.json"; - break; - - // LESS Entries - case "LessCssVariableDeclaration": - styleName = "variable.other.less"; - break; - case "LessCssVariableReference": - styleName = "variable.other.less"; - break; - case "LessCssNamespaceReference": - styleName = "variable.other.less"; - break; - case "LessCssMixinReference": - styleName = "variable.other.less"; - break; - case "LessCssMixinDeclaration": - styleName = "variable.other.less"; - break; - case "LessCssKeyword": - styleName = "punctuation.definition.keyword.css"; - break; - - // Scss Entries - case "ScssMixinReference": - styleName = "variable.other.less"; - break; - case "ScssMixinDeclaration": - styleName = "variable.other.less"; - break; - case "ScssVariableDeclaration": - styleName = "variable.other.less"; - break; - case "ScssVariableReference": - styleName = "variable.other.less"; - break; - default: - // If the stylename looks like a textmate style, just use it - if (classificationName.IndexOf ('.') >= 0) { - styleName = classificationName; - } - - break; - } - - return styleName; + }
+
+ private string GetStyleNameFromClassificationName (string classificationName)
+ {
+ string styleName = null;
+
+ // MONO: TODO: get this from the EditorFormat?
+ switch (classificationName) {
+ // MONO: TODO: Make each language MEF export this knowledge?
+
+ // CSS Entries
+ case "CSS Comment":
+ styleName = "comment.block.css";
+ break;
+ case "CSS Keyword":
+ styleName = "keyword.other.css";
+ break;
+ case "CSS Selector":
+ styleName = "entity.name.tag.css";
+ break;
+ case "CSS Property Name":
+ styleName = "support.type.property-name.css";
+ break;
+ case "CSS Property Value":
+ styleName = "support.constant.property-value.css";
+ break;
+ case "CSS String Value":
+ styleName = "string.quoted.double.css";
+ break;
+
+ // HTML Entries
+ case "HTML Attribute Name":
+ styleName = "entity.other.attribute-name.html";
+ break;
+ case "HTML Attribute Value":
+ styleName = "string.unquoted.html";
+ break;
+ case "HTML Comment":
+ styleName = "comment.block.html";
+ break;
+ case "HTML Element Name":
+ styleName = "entity.name.tag.html";
+ break;
+ case "HTML Entity":
+ styleName = "constant.character.entity.html";
+ break;
+ case "HTML Operator":
+ styleName = "punctuation.separator.key-value.html";
+ break;
+ case "HTML Server-Side Script":
+ //styleName = "punctuation.section.embedded.begin"; // suggested by mike, does nothing
+ //styleName = "punctuation.section.embedded.begin.cs"; // suggested by mike, does nothing
+ styleName = "meta.preprocessor.source.cs"; // TODO: Find a name to use here
+ //styleName = style.HtmlServerSideScript.Name;
+ break;
+ case "HTML Tag Delimiter":
+ styleName = "punctuation.definition.tag.begin.html";
+ break;
+ case "RazorCode":
+ //styleName = style.RazorCode.Name;
+ break;
+ case "RazorTagHelperAttribute":
+ styleName = "markup.bold";
+ break;
+ case "RazorTagHelperElement":
+ styleName = "markup.bold";
+ break;
+
+ // JSON Entries
+ case "operator":
+ styleName = "meta.structure.dictionary.value.json";
+ break;
+ case "string":
+ styleName = "string.quoted.double.json";
+ break;
+ case "keyword":
+ styleName = "constant.language.json";
+ break;
+ case "number":
+ styleName = "constant.numeric.json";
+ break;
+ case "comment":
+ styleName = "comment.block.json";
+ break;
+ case "JSON Property Name":
+ styleName = "support.type.property-name.json";
+ break;
+
+ // LESS Entries
+ case "LessCssVariableDeclaration":
+ styleName = "variable.other.less";
+ break;
+ case "LessCssVariableReference":
+ styleName = "variable.other.less";
+ break;
+ case "LessCssNamespaceReference":
+ styleName = "variable.other.less";
+ break;
+ case "LessCssMixinReference":
+ styleName = "variable.other.less";
+ break;
+ case "LessCssMixinDeclaration":
+ styleName = "variable.other.less";
+ break;
+ case "LessCssKeyword":
+ styleName = "punctuation.definition.keyword.css";
+ break;
+
+ // Scss Entries
+ case "ScssMixinReference":
+ styleName = "variable.other.less";
+ break;
+ case "ScssMixinDeclaration":
+ styleName = "variable.other.less";
+ break;
+ case "ScssVariableDeclaration":
+ styleName = "variable.other.less";
+ break;
+ case "ScssVariableReference":
+ styleName = "variable.other.less";
+ break;
+ default:
+ // If the stylename looks like a textmate style, just use it
+ if (classificationName.IndexOf ('.') >= 0) {
+ styleName = classificationName;
+ }
+
+ break;
+ }
+
+ return styleName;
}
static ScopeStack MakeScope (ScopeStack defaultScope, string scope)
@@ -445,10 +453,10 @@ namespace Microsoft.VisualStudio.Platform classificationMapCache = classificationMapCache.SetItem (scope, result);
return result;
- } - - public void Dispose () - { - } + }
+
+ public void Dispose ()
+ {
+ }
}
}
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/DefaultCommandTextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/DefaultCommandTextEditorExtension.cs index 747ed32eaf..4d2ff642ea 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/DefaultCommandTextEditorExtension.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/DefaultCommandTextEditorExtension.cs @@ -103,7 +103,7 @@ namespace MonoDevelop.Ide.Editor.Extension [CommandUpdateHandler (EditCommands.AddCodeComment)] [CommandUpdateHandler (EditCommands.RemoveCodeComment)] [CommandUpdateHandler (EditCommands.ToggleCodeComment)] - void OnUpdateToggleComment (CommandInfo info) + internal void OnUpdateToggleComment (CommandInfo info) { var scope = Editor.SyntaxHighlighting.GetScopeStackAsync (Editor.CaretOffset, CancellationToken.None).WaitAndGetResult (CancellationToken.None); var lang = TextMateLanguage.Create (scope); diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.Editor/Commands/CodeCommentTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.Editor/Commands/CodeCommentTests.cs index c14e1a4253..3864525e13 100644 --- a/main/tests/Ide.Tests/MonoDevelop.Ide.Editor/Commands/CodeCommentTests.cs +++ b/main/tests/Ide.Tests/MonoDevelop.Ide.Editor/Commands/CodeCommentTests.cs @@ -27,6 +27,8 @@ using System.Text; using NUnit.Framework; using MonoDevelop.Ide.Editor.Extension; using MonoDevelop.Ide.Gui; +using System.Threading.Tasks; +using MonoDevelop.Core; namespace MonoDevelop.Ide.Editor { @@ -172,6 +174,34 @@ namespace MonoDevelop.Ide.Editor } [Test] + public async Task TestToggle_Visible () + { + IdeApp.Initialize (new Core.ProgressMonitor ()); + //This dummyEditor is just so we can reuse CreateTextEditor code + //to resolve offset for us + var dummyEditor = CreateTextEditor (@"class Foo +{ + void Bar () + { + //$test + } +}"); + //We need to create full document and not just editor + //so extensions are initialized which set custom C# + //tagger based syntax highligthing + var document = IdeApp.Workbench.NewDocument ("a.cs", "text/x-csharp", dummyEditor.Text); + document.Editor.CaretOffset = dummyEditor.CaretOffset; + //Call UpdateParseDocument so AdHock Roslyn Workspace is created for file + await document.UpdateParseDocument (); + var info = new Components.Commands.CommandInfo (); + //Finnaly call command Update so it sets values which we assert + GetExtension (document.Editor).OnUpdateToggleComment (info); + await document.Close (); + Assert.AreEqual (true, info.Visible); + Assert.AreEqual (true, info.Enabled); + } + + [Test] public void TestToggle_Add() { var editor = CreateTextEditor (@"class Foo |