├── art
└── screenshot.png
├── src
├── EditorConfig
│ ├── logo.png
│ ├── License.txt
│ ├── Classify
│ │ ├── EditorClassifierClassifierProvider.cs
│ │ └── EditorConfigClassifier.cs
│ ├── ContentType
│ │ └── EditorConfigContentTypeDefinition.cs
│ ├── source.extension.vsixmanifest
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Completion
│ │ ├── CompletionItem.cs
│ │ ├── EditorConfigCompletionSource.cs
│ │ └── EditorConfigCompletionController.cs
│ ├── EditorConfigTextViewCreationListener.cs
│ ├── Validation
│ │ └── EditorConfigErrorTag.cs
│ └── EditorConfig.csproj
└── EditorConfig.sln
├── .gitattributes
├── README.md
└── .gitignore
/art/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/EditorConfig/master/art/screenshot.png
--------------------------------------------------------------------------------
/src/EditorConfig/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/EditorConfig/master/src/EditorConfig/logo.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/src/EditorConfig/License.txt:
--------------------------------------------------------------------------------
1 | Copyright 2014 Mads Kristensen
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/src/EditorConfig/Classify/EditorClassifierClassifierProvider.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.Composition;
2 | using Microsoft.VisualStudio.Text;
3 | using Microsoft.VisualStudio.Text.Classification;
4 | using Microsoft.VisualStudio.Utilities;
5 |
6 | namespace EditorConfig
7 | {
8 | [Export(typeof(IClassifierProvider))]
9 | [ContentType(EditorConfigContentTypeDefinition.EditorConfigContentType)]
10 | class EditorConfigClassifierProvider : IClassifierProvider
11 | {
12 | [Import]
13 | public IClassificationTypeRegistryService Registry { get; set; }
14 |
15 | public IClassifier GetClassifier(ITextBuffer textBuffer)
16 | {
17 | return textBuffer.Properties.GetOrCreateSingletonProperty(() => new EditorConfigClassifier(Registry));
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/EditorConfig/ContentType/EditorConfigContentTypeDefinition.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.Composition;
2 | using Microsoft.VisualStudio.Utilities;
3 |
4 | namespace EditorConfig
5 | {
6 | class EditorConfigContentTypeDefinition
7 | {
8 | public const string EditorConfigContentType = "EditorConfig";
9 |
10 | [Export(typeof(ContentTypeDefinition))]
11 | [Name(EditorConfigContentType)]
12 | [BaseDefinition("code")]
13 | public ContentTypeDefinition IEditorConfigContentType { get; set; }
14 |
15 | [Export(typeof(FileExtensionToContentTypeDefinition))]
16 | [ContentType(EditorConfigContentType)]
17 | [FileExtension(".editorconfig")]
18 | public FileExtensionToContentTypeDefinition EditorConfigFileExtension { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | EditorConfig for Visual Studio
2 | ============
3 |
4 | [](https://ci.appveyor.com/project/madskristensen/editorconfig)
5 |
6 | **Note: This extension is unpublished on the VS Gallery.**
7 |
8 | Gives syntax highlighting, validation and Intellisense for .editorconfig files
9 |
10 | This is meant as a pull request to https://github.com/editorconfig/editorconfig-visualstudio
11 |
12 |
13 | ## Screenshot:
14 |
15 | 
16 |
17 | I can't compile your project, since I don't have VS 2010 installed.
18 |
19 | This code should be Visual Studio 2010+ compatible though. All you have to do
20 | is to copy over the file `EditorConfigTextViewCreationListener.cs` and the folders `Classify`, `Completion`, `validation` and `ContentType` to
21 | the .editorconfig VS extension project and then add the missing references.
22 |
23 | Sorry for such a lame pull request
24 |
--------------------------------------------------------------------------------
/src/EditorConfig/source.extension.vsixmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | .editorconfig Colorizer
6 | Colorizer and Intellisense for .editorconfig files
7 | License.txt
8 | logo.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/EditorConfig/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("EditorConfigEditor")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("EditorConfigEditor")]
13 | [assembly: AssemblyCopyright("")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // Version information for an assembly consists of the following four values:
23 | //
24 | // Major Version
25 | // Minor Version
26 | // Build Number
27 | // Revision
28 | //
29 | // You can specify all the values or you can default the Build and Revision Numbers
30 | // by using the '*' as shown below:
31 | // [assembly: AssemblyVersion("1.0.*")]
32 | [assembly: AssemblyVersion("1.0.0.0")]
33 | [assembly: AssemblyFileVersion("1.0.0.0")]
34 |
--------------------------------------------------------------------------------
/src/EditorConfig.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.30722.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EditorConfig", "EditorConfig\EditorConfig.csproj", "{0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D0ED7743-20D1-45E1-9BEB-BC62CDE60D0F}"
9 | ProjectSection(SolutionItems) = preProject
10 | ..\.gitignore = ..\.gitignore
11 | ..\README.md = ..\README.md
12 | EndProjectSection
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | CI|Any CPU = CI|Any CPU
17 | Debug|Any CPU = Debug|Any CPU
18 | Release|Any CPU = Release|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}.CI|Any CPU.ActiveCfg = CI|Any CPU
22 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}.CI|Any CPU.Build.0 = CI|Any CPU
23 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}.Release|Any CPU.ActiveCfg = Release|Any CPU
26 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}.Release|Any CPU.Build.0 = Release|Any CPU
27 | EndGlobalSection
28 | GlobalSection(SolutionProperties) = preSolution
29 | HideSolutionNode = FALSE
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/src/EditorConfig/Completion/CompletionItem.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace EditorConfig
5 | {
6 | class CompletionItem
7 | {
8 | private static List _dic = new List
9 | {
10 | {new CompletionItem("root", "Special property that should be specified at the top of the file outside of any sections. Set to “true” to stop .editorconfig files search on current file.", "true")},
11 | {new CompletionItem("indent_style", "Indentation Style", "tab", "space")},
12 | {new CompletionItem("indent_size", "Indentation Size (in single-spaced characters)", "tab") },
13 | {new CompletionItem("tab_width", "Width of a single tabstop character") },
14 | {new CompletionItem("end_of_line", "Line ending file format (Unix, DOS, Mac)", "lf", "crlf", "cr") },
15 | {new CompletionItem("charset", "File character encoding", "latin1", "utf-8", "utf-1be", "utf-1le")},
16 | {new CompletionItem("trim_trailing_whitespace", "Denotes whether whitespace is allowed at the end of lines", "true", "false")},
17 | {new CompletionItem("insert_final_newline", "Denotes whether file should end with a newline", "true", "false")},
18 | {new CompletionItem("max_line_length", "Forces hard line wrapping after the amount of characters specified")},
19 | };
20 |
21 | private CompletionItem(string name, string description, params string[] values)
22 | {
23 | this.Name = name;
24 | this.Description = description;
25 | this.Values = values;
26 | }
27 |
28 | public static IEnumerable Items
29 | {
30 | get { return _dic; }
31 | }
32 |
33 | public static CompletionItem GetCompletionItem(string name)
34 | {
35 | return _dic.SingleOrDefault(c => c.Name == name);
36 | }
37 |
38 | public string Name { get; set; }
39 | public string Description { get; set; }
40 | public IEnumerable Values { get; set; }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/EditorConfig/EditorConfigTextViewCreationListener.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.Composition;
3 | using Microsoft.VisualStudio.Editor;
4 | using Microsoft.VisualStudio.Language.Intellisense;
5 | using Microsoft.VisualStudio.OLE.Interop;
6 | using Microsoft.VisualStudio.Shell;
7 | using Microsoft.VisualStudio.Text.Editor;
8 | using Microsoft.VisualStudio.TextManager.Interop;
9 | using Microsoft.VisualStudio.Utilities;
10 |
11 | namespace EditorConfig
12 | {
13 | [Export(typeof(IVsTextViewCreationListener))]
14 | [ContentType(EditorConfigContentTypeDefinition.EditorConfigContentType)]
15 | [TextViewRole(PredefinedTextViewRoles.Interactive)]
16 | internal sealed class VsTextViewCreationListener : IVsTextViewCreationListener
17 | {
18 | [Import]
19 | IVsEditorAdaptersFactoryService AdaptersFactory = null;
20 |
21 | [Import]
22 | ICompletionBroker CompletionBroker = null;
23 |
24 | [Import]
25 | internal SVsServiceProvider ServiceProvider = null;
26 |
27 | private ErrorListProvider _errorList;
28 |
29 | public void VsTextViewCreated(IVsTextView textViewAdapter)
30 | {
31 | IWpfTextView view = AdaptersFactory.GetWpfTextView(textViewAdapter);
32 |
33 | view.TextBuffer.Properties.GetOrCreateSingletonProperty(() => view);
34 | _errorList = view.TextBuffer.Properties.GetOrCreateSingletonProperty(() => new ErrorListProvider(ServiceProvider));
35 |
36 | if (_errorList == null)
37 | return;
38 |
39 | CommandFilter filter = new CommandFilter(view, CompletionBroker);
40 |
41 | IOleCommandTarget next;
42 | textViewAdapter.AddCommandFilter(filter, out next);
43 | filter.Next = next;
44 |
45 | view.Closed += OnViewClosed;
46 | }
47 |
48 | private void OnViewClosed(object sender, EventArgs e)
49 | {
50 | IWpfTextView view = (IWpfTextView)sender;
51 | view.Closed -= OnViewClosed;
52 |
53 | if (_errorList != null)
54 | {
55 | _errorList.Tasks.Clear();
56 | _errorList.Dispose();
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/EditorConfig/Classify/EditorConfigClassifier.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text.RegularExpressions;
5 | using Microsoft.VisualStudio.Language.StandardClassification;
6 | using Microsoft.VisualStudio.Text;
7 | using Microsoft.VisualStudio.Text.Classification;
8 |
9 | namespace EditorConfig
10 | {
11 | class EditorConfigClassifier : IClassifier
12 | {
13 | private static Regex _rxKeywords = new Regex(@"(?<=\=\s?)([a-zA-Z0-9-]+)\b", RegexOptions.Compiled);
14 | private static Regex _rxIdentifier = new Regex(@"^([^=]+)\b(?=\=?)", RegexOptions.Compiled);
15 | private static Regex _rxString = new Regex(@"\[([^\]]+)\]", RegexOptions.Compiled);
16 | private static Regex _rxComment = new Regex(@"#.*", RegexOptions.Compiled);
17 | private static List> _map;
18 |
19 | public EditorConfigClassifier(IClassificationTypeRegistryService registry)
20 | {
21 | if (_map == null)
22 | _map = new List>
23 | {
24 | {Tuple.Create(_rxComment, registry.GetClassificationType(PredefinedClassificationTypeNames.Comment))},
25 | {Tuple.Create(_rxString, registry.GetClassificationType(PredefinedClassificationTypeNames.String))},
26 | {Tuple.Create(_rxIdentifier, registry.GetClassificationType(PredefinedClassificationTypeNames.SymbolDefinition))},
27 | {Tuple.Create(_rxKeywords, registry.GetClassificationType(PredefinedClassificationTypeNames.Literal))},
28 | };
29 | }
30 |
31 | public IList GetClassificationSpans(SnapshotSpan span)
32 | {
33 | IList list = new List();
34 | ITextSnapshotLine line = span.Start.GetContainingLine();
35 | string text = line.GetText();
36 |
37 | foreach (var tuple in _map)
38 | foreach (Match match in tuple.Item1.Matches(text))
39 | {
40 | var str = new SnapshotSpan(line.Snapshot, line.Start.Position + match.Index, match.Length);
41 |
42 | // Make sure we don't double classify
43 | if (list.Any(s => s.Span.IntersectsWith(str)))
44 | continue;
45 |
46 | list.Add(new ClassificationSpan(str, tuple.Item2));
47 | }
48 |
49 | return list;
50 | }
51 |
52 | public event EventHandler ClassificationChanged
53 | {
54 | add { }
55 | remove { }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # MSTest test Results
20 | [Tt]est[Rr]esult*/
21 | [Bb]uild[Ll]og.*
22 |
23 | #NUNIT
24 | *.VisualState.xml
25 | TestResult.xml
26 |
27 | # Build Results of an ATL Project
28 | [Dd]ebugPS/
29 | [Rr]eleasePS/
30 | dlldata.c
31 |
32 | *_i.c
33 | *_p.c
34 | *_i.h
35 | *.ilk
36 | *.meta
37 | *.obj
38 | *.pch
39 | *.pdb
40 | *.pgc
41 | *.pgd
42 | *.rsp
43 | *.sbr
44 | *.tlb
45 | *.tli
46 | *.tlh
47 | *.tmp
48 | *.tmp_proj
49 | *.log
50 | *.vspscc
51 | *.vssscc
52 | .builds
53 | *.pidb
54 | *.svclog
55 | *.scc
56 |
57 | # Chutzpah Test files
58 | _Chutzpah*
59 |
60 | # Visual C++ cache files
61 | ipch/
62 | *.aps
63 | *.ncb
64 | *.opensdf
65 | *.sdf
66 | *.cachefile
67 |
68 | # Visual Studio profiler
69 | *.psess
70 | *.vsp
71 | *.vspx
72 |
73 | # TFS 2012 Local Workspace
74 | $tf/
75 |
76 | # Guidance Automation Toolkit
77 | *.gpState
78 |
79 | # ReSharper is a .NET coding add-in
80 | _ReSharper*/
81 | *.[Rr]e[Ss]harper
82 | *.DotSettings.user
83 |
84 | # JustCode is a .NET coding addin-in
85 | .JustCode
86 |
87 | # TeamCity is a build add-in
88 | _TeamCity*
89 |
90 | # DotCover is a Code Coverage Tool
91 | *.dotCover
92 |
93 | # NCrunch
94 | *.ncrunch*
95 | _NCrunch_*
96 | .*crunch*.local.xml
97 |
98 | # MightyMoose
99 | *.mm.*
100 | AutoTest.Net/
101 |
102 | # Web workbench (sass)
103 | .sass-cache/
104 |
105 | # Installshield output folder
106 | [Ee]xpress/
107 |
108 | # DocProject is a documentation generator add-in
109 | DocProject/buildhelp/
110 | DocProject/Help/*.HxT
111 | DocProject/Help/*.HxC
112 | DocProject/Help/*.hhc
113 | DocProject/Help/*.hhk
114 | DocProject/Help/*.hhp
115 | DocProject/Help/Html2
116 | DocProject/Help/html
117 |
118 | # Click-Once directory
119 | publish/
120 |
121 | # Publish Web Output
122 | *.[Pp]ublish.xml
123 | *.azurePubxml
124 |
125 | # NuGet Packages Directory
126 | packages/
127 | ## TODO: If the tool you use requires repositories.config uncomment the next line
128 | #!packages/repositories.config
129 |
130 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
131 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
132 | !packages/build/
133 |
134 | # Windows Azure Build Output
135 | csx/
136 | *.build.csdef
137 |
138 | # Windows Store app package directory
139 | AppPackages/
140 |
141 | # Others
142 | sql/
143 | *.Cache
144 | ClientBin/
145 | [Ss]tyle[Cc]op.*
146 | ~$*
147 | *~
148 | *.dbmdl
149 | *.dbproj.schemaview
150 | *.pfx
151 | *.publishsettings
152 | node_modules/
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | *.mdf
166 | *.ldf
167 |
168 | # Business Intelligence projects
169 | *.rdl.data
170 | *.bim.layout
171 | *.bim_*.settings
172 |
173 | # Microsoft Fakes
174 | FakesAssemblies/
175 |
176 | # =========================
177 | # Operating System Files
178 | # =========================
179 |
180 | # OSX
181 | # =========================
182 |
183 | .DS_Store
184 | .AppleDouble
185 | .LSOverride
186 |
187 | # Icon must ends with two \r.
188 | Icon
189 |
190 | # Thumbnails
191 | ._*
192 |
193 | # Files that might appear on external disk
194 | .Spotlight-V100
195 | .Trashes
196 |
197 | # Windows
198 | # =========================
199 |
200 | # Windows image file caches
201 | Thumbs.db
202 | ehthumbs.db
203 |
204 | # Folder config file
205 | Desktop.ini
206 |
207 | # Recycle Bin used on file shares
208 | $RECYCLE.BIN/
209 |
210 | # Windows Installer files
211 | *.cab
212 | *.msi
213 | *.msm
214 | *.msp
215 |
--------------------------------------------------------------------------------
/src/EditorConfig/Completion/EditorConfigCompletionSource.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.Composition;
3 | using System.Linq;
4 | using System.Windows.Media;
5 | using Microsoft.VisualStudio.Language.Intellisense;
6 | using Microsoft.VisualStudio.Language.StandardClassification;
7 | using Microsoft.VisualStudio.Text;
8 | using Microsoft.VisualStudio.Text.Classification;
9 | using Microsoft.VisualStudio.Text.Operations;
10 | using Microsoft.VisualStudio.Utilities;
11 | using Intel = Microsoft.VisualStudio.Language.Intellisense;
12 |
13 | namespace EditorConfig
14 | {
15 | [Export(typeof(ICompletionSourceProvider))]
16 | [ContentType(EditorConfigContentTypeDefinition.EditorConfigContentType)]
17 | [Name("Editor Config Completion")]
18 | class EditorConfigCompletionSourceProvider : ICompletionSourceProvider
19 | {
20 | [Import]
21 | IClassifierAggregatorService ClassifierAggregatorService = null;
22 |
23 | [Import]
24 | ITextStructureNavigatorSelectorService NavigatorService = null;
25 |
26 | [Import]
27 | IGlyphService GlyphService = null;
28 |
29 | private static ImageSource _glyph;
30 |
31 | public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer)
32 | {
33 | if (_glyph == null)
34 | _glyph = GlyphService.GetGlyph(StandardGlyphGroup.GlyphGroupProperty, StandardGlyphItem.GlyphItemPublic);
35 |
36 | return new EditorConfigCompletionSource(textBuffer, ClassifierAggregatorService, NavigatorService, _glyph);
37 | }
38 | }
39 |
40 | class EditorConfigCompletionSource : ICompletionSource
41 | {
42 | private ITextBuffer _buffer;
43 | private bool _disposed = false;
44 | private IClassifier _classifier;
45 | private ITextStructureNavigatorSelectorService _navigator;
46 | private ImageSource _glyph;
47 |
48 | public EditorConfigCompletionSource(ITextBuffer buffer, IClassifierAggregatorService classifier, ITextStructureNavigatorSelectorService navigator, ImageSource glyph)
49 | {
50 | _buffer = buffer;
51 | _classifier = classifier.GetClassifier(buffer);
52 | _navigator = navigator;
53 | _glyph = glyph;
54 | }
55 |
56 | public void AugmentCompletionSession(ICompletionSession session, IList completionSets)
57 | {
58 | if (_disposed)
59 | return;
60 |
61 | ITextSnapshot snapshot = _buffer.CurrentSnapshot;
62 | var triggerPoint = session.GetTriggerPoint(snapshot);
63 |
64 | if (triggerPoint == null)
65 | return;
66 |
67 | SnapshotSpan extent = FindTokenSpanAtPosition(session).GetSpan(snapshot);
68 | var line = triggerPoint.Value.GetContainingLine().Extent;
69 |
70 | var spans = _classifier.GetClassificationSpans(line);
71 |
72 | List list = new List();
73 | string current = string.Empty;
74 |
75 | foreach (var span in spans)
76 | {
77 | if (span.ClassificationType.IsOfType(PredefinedClassificationTypeNames.SymbolDefinition))
78 | {
79 | current = span.Span.GetText();
80 |
81 | if (!span.Span.Contains(extent))
82 | continue;
83 |
84 | foreach (var key in CompletionItem.Items)
85 | list.Add(CreateCompletion(key.Name, key.Description));
86 | }
87 | else if (span.ClassificationType.IsOfType(PredefinedClassificationTypeNames.Literal))
88 | {
89 | if (!span.Span.Contains(extent))
90 | continue;
91 |
92 | CompletionItem item = CompletionItem.GetCompletionItem(current);
93 | if (item != null){
94 | foreach (var value in item.Values)
95 | list.Add(CreateCompletion(value));
96 | }}
97 | }
98 |
99 | var applicableTo = snapshot.CreateTrackingSpan(extent, SpanTrackingMode.EdgeInclusive);
100 |
101 | completionSets.Add(new CompletionSet("All", "All", applicableTo, list, Enumerable.Empty()));
102 | }
103 |
104 | private Completion CreateCompletion(string name, string description = null)
105 | {
106 | return new Completion(name, name, description, _glyph, null);
107 | }
108 |
109 | private ITrackingSpan FindTokenSpanAtPosition(ICompletionSession session)
110 | {
111 | SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1;
112 | ITextStructureNavigator navigator = _navigator.GetTextStructureNavigator(_buffer);
113 | TextExtent extent = navigator.GetExtentOfWord(currentPoint);
114 | return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
115 | }
116 |
117 | public void Dispose()
118 | {
119 | _disposed = true;
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/src/EditorConfig/Completion/EditorConfigCompletionController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using Microsoft.VisualStudio;
4 | using Microsoft.VisualStudio.Language.Intellisense;
5 | using Microsoft.VisualStudio.OLE.Interop;
6 | using Microsoft.VisualStudio.Text;
7 | using Microsoft.VisualStudio.Text.Editor;
8 |
9 | namespace EditorConfig
10 | {
11 | internal sealed class CommandFilter : IOleCommandTarget
12 | {
13 | private ICompletionSession _currentSession;
14 |
15 | public CommandFilter(IWpfTextView textView, ICompletionBroker broker)
16 | {
17 | _currentSession = null;
18 |
19 | TextView = textView;
20 | Broker = broker;
21 | }
22 |
23 | public IWpfTextView TextView { get; private set; }
24 | public ICompletionBroker Broker { get; private set; }
25 | public IOleCommandTarget Next { get; set; }
26 |
27 | private static char GetTypeChar(IntPtr pvaIn)
28 | {
29 | return (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
30 | }
31 |
32 | public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
33 | {
34 | bool handled = false;
35 | int hresult = VSConstants.S_OK;
36 |
37 | // 1. Pre-process
38 | if (pguidCmdGroup == VSConstants.VSStd2K)
39 | {
40 | switch ((VSConstants.VSStd2KCmdID)nCmdID)
41 | {
42 | case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
43 | case VSConstants.VSStd2KCmdID.COMPLETEWORD:
44 | case VSConstants.VSStd2KCmdID.SHOWMEMBERLIST:
45 | handled = StartSession();
46 | break;
47 | case VSConstants.VSStd2KCmdID.RETURN:
48 | handled = Complete(false);
49 | break;
50 | case VSConstants.VSStd2KCmdID.TAB:
51 | handled = Complete(true);
52 | break;
53 | case VSConstants.VSStd2KCmdID.CANCEL:
54 | handled = Cancel();
55 | break;
56 | }
57 | }
58 |
59 | if (!handled)
60 | hresult = Next.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
61 |
62 | if (ErrorHandler.Succeeded(hresult))
63 | {
64 | if (pguidCmdGroup == VSConstants.VSStd2K)
65 | {
66 | switch ((VSConstants.VSStd2KCmdID)nCmdID)
67 | {
68 | case VSConstants.VSStd2KCmdID.TYPECHAR:
69 | char ch = GetTypeChar(pvaIn);
70 | if (ch == '=' || ch == ' ')
71 | Cancel();
72 | else if (!char.IsPunctuation(ch) && !char.IsControl(ch))
73 | StartSession();
74 | else if (_currentSession != null)
75 | Filter();
76 | break;
77 | case VSConstants.VSStd2KCmdID.BACKSPACE:
78 | if (_currentSession == null)
79 | StartSession();
80 |
81 | Filter();
82 | break;
83 | }
84 | }
85 | }
86 |
87 | return hresult;
88 | }
89 |
90 | private void Filter()
91 | {
92 | if (_currentSession == null)
93 | return;
94 |
95 | _currentSession.SelectedCompletionSet.SelectBestMatch();
96 | _currentSession.SelectedCompletionSet.Recalculate();
97 | }
98 |
99 | bool Cancel()
100 | {
101 | if (_currentSession == null)
102 | return false;
103 |
104 | _currentSession.Dismiss();
105 |
106 | return true;
107 | }
108 |
109 | bool Complete(bool force)
110 | {
111 | if (_currentSession == null)
112 | return false;
113 |
114 | if (!_currentSession.SelectedCompletionSet.SelectionStatus.IsSelected && !force)
115 | {
116 | _currentSession.Dismiss();
117 | return false;
118 | }
119 | else
120 | {
121 | _currentSession.Commit();
122 | return true;
123 | }
124 | }
125 |
126 | bool StartSession()
127 | {
128 | if (_currentSession != null)
129 | return false;
130 |
131 | SnapshotPoint caret = TextView.Caret.Position.BufferPosition;
132 | ITextSnapshot snapshot = caret.Snapshot;
133 |
134 | if (!Broker.IsCompletionActive(TextView))
135 | {
136 | _currentSession = Broker.CreateCompletionSession(TextView, snapshot.CreateTrackingPoint(caret, PointTrackingMode.Positive), true);
137 | }
138 | else
139 | {
140 | _currentSession = Broker.GetSessions(TextView)[0];
141 | }
142 | _currentSession.Dismissed += (sender, args) => _currentSession = null;
143 |
144 | if (!_currentSession.IsStarted)
145 | _currentSession.Start();
146 |
147 | return true;
148 | }
149 |
150 | public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
151 | {
152 | if (pguidCmdGroup == VSConstants.VSStd2K)
153 | {
154 | switch ((VSConstants.VSStd2KCmdID)prgCmds[0].cmdID)
155 | {
156 | case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
157 | case VSConstants.VSStd2KCmdID.COMPLETEWORD:
158 | case VSConstants.VSStd2KCmdID.SHOWMEMBERLIST:
159 | prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED;
160 | return VSConstants.S_OK;
161 | }
162 | }
163 | return Next.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
164 | }
165 | }
166 | }
--------------------------------------------------------------------------------
/src/EditorConfig/Validation/EditorConfigErrorTag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.Composition;
4 | using System.Linq;
5 | using Microsoft.VisualStudio.Language.StandardClassification;
6 | using Microsoft.VisualStudio.Shell;
7 | using Microsoft.VisualStudio.Text;
8 | using Microsoft.VisualStudio.Text.Classification;
9 | using Microsoft.VisualStudio.Text.Editor;
10 | using Microsoft.VisualStudio.Text.Tagging;
11 | using Microsoft.VisualStudio.Utilities;
12 |
13 | namespace EditorConfig
14 | {
15 | [Export(typeof(ITaggerProvider))]
16 | [ContentType(EditorConfigContentTypeDefinition.EditorConfigContentType)]
17 | [TagType(typeof(ErrorTag))]
18 | class CheckTextErrorProvider : ITaggerProvider
19 | {
20 | [Import]
21 | IClassifierAggregatorService _classifierAggregatorService = null;
22 |
23 | [Import]
24 | public ITextDocumentFactoryService TextDocumentFactoryService { get; set; }
25 |
26 | public ITagger CreateTagger(ITextBuffer buffer) where T : ITag
27 | {
28 | if (buffer == null)
29 | throw new ArgumentException("Buffer is null");
30 |
31 | var errorlist = buffer.Properties.GetProperty(typeof(ErrorListProvider)) as ErrorListProvider;
32 | var view = buffer.Properties.GetProperty(typeof(IWpfTextView)) as IWpfTextView;
33 |
34 | ITextDocument document;
35 | if (TextDocumentFactoryService.TryGetTextDocument(buffer, out document) && errorlist != null)
36 | {
37 | return new CheckTextErrorTagger(view, _classifierAggregatorService, errorlist, document) as ITagger;
38 | }
39 |
40 | return null;
41 | }
42 | }
43 |
44 | class CheckTextErrorTagger : ITagger
45 | {
46 | private IClassifier _classifier;
47 | private ErrorListProvider _errorlist;
48 | private ITextDocument _document;
49 | private IWpfTextView _view;
50 |
51 | public CheckTextErrorTagger(IWpfTextView view, IClassifierAggregatorService classifier, ErrorListProvider errorlist, ITextDocument document)
52 | {
53 | _view = view;
54 | _classifier = classifier.GetClassifier(view.TextBuffer);
55 | _errorlist = errorlist;
56 | _document = document;
57 | }
58 |
59 | public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans)
60 | {
61 | var span = spans[0];
62 | var line = span.Start.GetContainingLine();
63 | var classificationSpans = _classifier.GetClassificationSpans(line.Extent);
64 | string property = null;
65 |
66 | ClearError(line);
67 |
68 | foreach (var cspan in classificationSpans)
69 | {
70 | if (cspan.ClassificationType.IsOfType(PredefinedClassificationTypeNames.SymbolDefinition))
71 | {
72 | property = cspan.Span.GetText();
73 | CompletionItem item = CompletionItem.GetCompletionItem(property);
74 |
75 | if (item == null)
76 | yield return CreateError(line, cspan, "\"" + property + "\" is not a valid .editorconfig property"); ;
77 | }
78 | else if (cspan.ClassificationType.IsOfType(PredefinedClassificationTypeNames.Literal))
79 | {
80 | if (string.IsNullOrEmpty(property))
81 | continue;
82 |
83 | CompletionItem item = CompletionItem.GetCompletionItem(property);
84 | if (item == null)
85 | continue;
86 |
87 | string value = cspan.Span.GetText();
88 | int intValue;
89 |
90 | if (!item.Values.Contains(value) && !int.TryParse(value, out intValue))
91 | yield return CreateError(line, cspan, "\"" + value + "\" is not a valid value for the '" + property + "' property");
92 | }
93 | }
94 | }
95 |
96 | private TagSpan CreateError(ITextSnapshotLine line, ClassificationSpan cspan, string message)
97 | {
98 | ErrorTask task = CreateErrorTask(line, cspan, message);
99 |
100 | _errorlist.Tasks.Add(task);
101 |
102 | SnapshotSpan CheckTextSpan = new SnapshotSpan(cspan.Span.Snapshot, new Span(cspan.Span.Start, cspan.Span.Length));
103 | return new TagSpan(CheckTextSpan, new ErrorTag(message, message));
104 | }
105 |
106 | private ErrorTask CreateErrorTask(ITextSnapshotLine line, ClassificationSpan cspan, string text)
107 | {
108 | ErrorTask task = new ErrorTask
109 | {
110 | Text = text,
111 | Line = line.LineNumber,
112 | Column = cspan.Span.Start.Position - line.Start.Position,
113 | Category = TaskCategory.Misc,
114 | ErrorCategory = TaskErrorCategory.Warning,
115 | Priority = TaskPriority.Low,
116 | Document = _document.FilePath
117 | };
118 |
119 | task.Navigate += task_Navigate;
120 |
121 | return task;
122 | }
123 |
124 | private void task_Navigate(object sender, EventArgs e)
125 | {
126 | ErrorTask task = (ErrorTask)sender;
127 | _errorlist.Navigate(task, new Guid("{00000000-0000-0000-0000-000000000000}"));
128 |
129 | var line = _view.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(task.Line);
130 | var point = new SnapshotPoint(line.Snapshot, line.Start.Position + task.Column);
131 | _view.Caret.MoveTo(point);
132 | }
133 |
134 | private void ClearError(ITextSnapshotLine line)
135 | {
136 | foreach (ErrorTask existing in _errorlist.Tasks)
137 | {
138 | if (existing.Line == line.LineNumber)
139 | {
140 | _errorlist.Tasks.Remove(existing);
141 | break;
142 | }
143 | }
144 | }
145 |
146 |
147 | public event EventHandler TagsChanged
148 | {
149 | add { }
150 | remove { }
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/EditorConfig/EditorConfig.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 12.0
5 | 11.0
6 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
7 |
8 |
9 | 12.0
10 |
11 | publish\
12 | true
13 | Disk
14 | false
15 | Foreground
16 | 7
17 | Days
18 | false
19 | false
20 | true
21 | 0
22 | 1.0.0.%2a
23 | false
24 | false
25 | true
26 | Program
27 | $(DevEnvDir)\devenv.exe
28 | /rootsuffix Exp
29 |
30 |
31 | bin\CI\
32 | TRACE
33 | true
34 | pdbonly
35 | AnyCPU
36 | prompt
37 | MinimumRecommendedRules.ruleset
38 | False
39 |
40 |
41 |
42 | Debug
43 | AnyCPU
44 | 2.0
45 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
46 | {0439E23F-FBE4-48FB-8A08-1BCFF2A8854F}
47 | Library
48 | Properties
49 | EditorConfigEditor
50 | EditorConfigEditor
51 | v4.5
52 | false
53 | true
54 | false
55 | false
56 | false
57 | false
58 |
59 |
60 | true
61 | full
62 | false
63 | bin\Debug\
64 | DEBUG;TRACE
65 | prompt
66 | 4
67 |
68 |
69 | pdbonly
70 | true
71 | bin\Release\
72 | TRACE
73 | prompt
74 | 4
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | Designer
90 |
91 |
92 |
93 |
94 | False
95 | Microsoft .NET Framework 4.5 %28x86 and x64%29
96 | true
97 |
98 |
99 | False
100 | .NET Framework 3.5 SP1 Client Profile
101 | false
102 |
103 |
104 | False
105 | .NET Framework 3.5 SP1
106 | false
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Always
132 | true
133 |
134 |
135 | Always
136 | true
137 |
138 |
139 |
140 |
141 |
148 |
--------------------------------------------------------------------------------