-
-
Notifications
You must be signed in to change notification settings - Fork 250
/
Copy pathSelectorQuickInfo.cs
101 lines (76 loc) · 3.32 KB
/
SelectorQuickInfo.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSS.Core;
using Microsoft.CSS.Editor;
using Microsoft.Less.Core;
using Microsoft.Scss.Core;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
namespace MadsKristensen.EditorExtensions
{
internal class SelectorQuickInfo : IQuickInfoSource
{
private ITextBuffer _buffer;
public SelectorQuickInfo(ITextBuffer subjectBuffer)
{
_buffer = subjectBuffer;
}
public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> qiContent, out ITrackingSpan applicableToSpan)
{
applicableToSpan = null;
if (session == null || qiContent == null)
return;
// Map the trigger point down to our buffer.
SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot);
if (!point.HasValue)
return;
var tree = CssEditorDocument.FromTextBuffer(_buffer);
ParseItem item = tree.StyleSheet.ItemBeforePosition(point.Value.Position);
if (item == null || !item.IsValid)
return;
Selector sel = item.FindType<Selector>();
if (sel == null)
return;
// Mixins don't have specificity
if (sel.SimpleSelectors.Count == 1)
{
var subSelectors = sel.SimpleSelectors[0].SubSelectors;
if (subSelectors.Count == 1 &&
subSelectors[0] is LessMixinDeclaration &&
subSelectors[0] is ScssMixinDeclaration)
return;
}
applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(item.Start, item.Length, SpanTrackingMode.EdgeNegative);
if (_buffer.ContentType.DisplayName.Equals("css", StringComparison.OrdinalIgnoreCase))
{
qiContent.Add(GenerateContent(sel));
return;
}
HandlePreprocessor(session, point.Value, item.FindType<Selector>(), qiContent);
}
private void HandlePreprocessor(IQuickInfoSession session, SnapshotPoint point, Selector item, IList<object> qiContent)
{
if (item == null || !session.TextView.Properties.ContainsProperty("CssSourceMap"))
return;
CssSourceMap sourceMap;
if (!session.TextView.Properties.TryGetProperty<CssSourceMap>("CssSourceMap", out sourceMap))
return;
var line = point.GetContainingLine().LineNumber;
var column = item.Start - point.Snapshot.GetLineFromPosition(item.Start).Start;
var node = sourceMap.MapNodes.FirstOrDefault(s =>
s.SourceFilePath == _buffer.GetFileName() &&
s.OriginalLine == line &&
s.OriginalColumn == column);
if (node == null)
return;
qiContent.Add(GenerateContent(node.GeneratedSelector));
}
private static string GenerateContent(Selector sel)
{
SelectorSpecificity specificity = new SelectorSpecificity(sel);
return "Selector specificity:\t\t" + specificity.ToString().Trim();
}
public void Dispose() { }
}
}