Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLluis Sanchez <llsan@microsoft.com>2018-05-25 19:21:35 +0300
committerGitHub <noreply@github.com>2018-05-25 19:21:35 +0300
commitf7b338b596748ffa52b2f86a292bb52a1ce2a4fd (patch)
tree69f4e002f046aa3b2444ed6cd4ba02a018f9fbbf
parent6f05bc6453f03e6401525e16341b244bbe34ed8c (diff)
parent7b736c39bbd344cc45d915790b79a07bbd9c2d25 (diff)
Merge pull request #4842 from mono/fix4822monodevelop-7.6.0.947
Fix #4822: Toggle line comment menu no longer exists
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/VSEditor/TagBasedSyntaxHighlighting.cs696
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/DefaultCommandTextEditorExtension.cs2
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.Editor/Commands/CodeCommentTests.cs30
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