Index: clang-tidy-vs/.gitignore
===================================================================
--- clang-tidy-vs/.gitignore
+++ clang-tidy-vs/.gitignore
@@ -5,3 +5,5 @@
clang-tidy.exe
packages/
*.csproj.user
+*.suo
+*.vsixmanifest
\ No newline at end of file
Index: clang-tidy-vs/CMakeLists.txt
===================================================================
--- clang-tidy-vs/CMakeLists.txt
+++ clang-tidy-vs/CMakeLists.txt
@@ -11,15 +11,25 @@
"${CLANG_SOURCE_DIR}/LICENSE.TXT"
"${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/license.txt")
+ # Build number added to Clang version to ensure that new VSIX can be upgraded
+ string(TIMESTAMP CLANG_TIDY_VSIX_BUILD %y%m%d%H%M UTC)
+
if (NOT CLANG_TIDY_VS_VERSION)
- set(CLANG_TIDY_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")
+ set(CLANG_TIDY_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}.${CLANG_TIDY_VSIX_BUILD}")
endif()
configure_file("source.extension.vsixmanifest.in"
"${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/source.extension.vsixmanifest")
+ find_program(NUGET_EXE nuget PATHS ${NUGET_EXE_DIR})
+ if (NOT NUGET_EXE)
+ message(FATAL_ERROR "Could not find nuget.exe. Download from https://www.nuget.org/nuget.exe"
+ " and add parent directory to PATH or pass it via NUGET_EXE_DIR var.")
+ endif()
+
add_custom_target(clang_tidy_vsix ALL
- devenv "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy.sln" /Build Release
+ COMMAND ${NUGET_EXE} restore "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy.sln"
+ COMMAND devenv "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy.sln" /Build Release
DEPENDS clang_tidy_exe_for_vsix "${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/source.extension.vsixmanifest"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/ClangTidy/bin/Release/ClangTidy.vsix"
Index: clang-tidy-vs/ClangTidy/ClangTidy.csproj
===================================================================
--- clang-tidy-vs/ClangTidy/ClangTidy.csproj
+++ clang-tidy-vs/ClangTidy/ClangTidy.csproj
@@ -59,26 +59,34 @@
false
+
+ True
+
+
-
+
+
+
+
+
+
+
-
-
..\packages\YamlDotNet.3.3.0\lib\net35\YamlDotNet.dll
True
@@ -89,42 +97,6 @@
-
- {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}
- 8
- 0
- 0
- primary
- False
- False
-
-
- {26AD1324-4B7C-44BC-84F8-B86AED45729F}
- 10
- 0
- 0
- primary
- False
- False
-
-
- {1A31287A-4D7D-413E-8E32-3B374931BD89}
- 8
- 0
- 0
- primary
- False
- False
-
-
- {2CE2370E-D744-4936-A090-3FFFE667B0E1}
- 9
- 0
- 0
- primary
- False
- False
-
{1CBA492E-7263-47BB-87FE-639000619B15}
8
@@ -145,6 +117,7 @@
+
@@ -155,6 +128,17 @@
Component
+
+
+
+
+
+
+
+
+
+
+
@@ -199,6 +183,9 @@
+
+ true
+
Designer
@@ -210,15 +197,13 @@
-
-
-
true
true
+
@@ -254,7 +239,7 @@
- if not exist $(ProjectDir)Key.snk ("$(SDKToolsPath)\sn.exe" -k $(ProjectDir)Key.snk)
+ if not exist $(ProjectDir)Key.snk ("$(FrameworkSDKDir)Bin\NETFX 4.6 Tools\sn.exe" -k $(ProjectDir)Key.snk)
Index: clang-tidy-vs/ClangTidy/ClangTidy.vsct
===================================================================
--- clang-tidy-vs/ClangTidy/ClangTidy.vsct
+++ clang-tidy-vs/ClangTidy/ClangTidy.vsct
@@ -21,8 +21,6 @@
-
-
@@ -34,6 +32,16 @@
group; your package should define its own command set in order to avoid collisions
with command ids defined by other packages. -->
+
+
+
-
+ must be the actual index (1-based) of the bitmap inside the bitmap strip. -->
+
@@ -101,17 +118,14 @@
+
+
-
-
-
-
-
-
-
-
+
+
+
Index: clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
===================================================================
--- clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
+++ clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
@@ -23,7 +23,6 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
-using System.Xml.Linq;
namespace LLVM.ClangTidy
{
@@ -51,6 +50,7 @@
private void MenuItemCallback(object sender, EventArgs args)
{
+ ClangTidyRunner.RunClangTidyProcess();
}
}
}
Index: clang-tidy-vs/ClangTidy/ClassifierAndTagger/Classifier.cs
===================================================================
--- /dev/null
+++ clang-tidy-vs/ClangTidy/ClassifierAndTagger/Classifier.cs
@@ -0,0 +1,81 @@
+´╗┐using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Text;
+
+namespace LLVM.ClangTidy
+{
+ ///
+ /// This class assigns classification types to given text by implicitly asking ValidationTagger
+ /// for text spans containing clang-tidy validation warnings in given text buffer.
+ /// Generally, the span in question is the displayed portion of the file currently open in the Editor.
+ ///
+ class Classifier : IClassifier
+ {
+ private IClassificationType ClassificationType;
+ private ITagAggregator Tagger;
+ private static Classifier ActiveClassifier = null;
+ private SnapshotSpan CurrentSpan;
+
+ internal Classifier(ITagAggregator tagger, IClassificationType classificationType)
+ {
+ Tagger = tagger;
+ ClassificationType = classificationType;
+ }
+
+ ///
+ /// Get every ValidationTag instance within the given span.
+ /// Usually a single SnapshotSpan is the content of one of the visible lines or
+ /// selections of text in the text editor and a Snapshot is the content of the
+ /// whole file opened in editor window.
+ ///
+ /// The span of text that will be searched for validation tags
+ /// A list of every relevant tag in the given span
+ public IList GetClassificationSpans(SnapshotSpan span)
+ {
+ ActiveClassifier = this;
+
+ // After clang-tidy returns new results, tags will be automatically created only for
+ // newly appearing text lines or focused code window.
+ // To force-refresh tags in current window, store single span for the whole file and
+ // call Invalidate() on this span when clang-tidy results are ready.
+ if (CurrentSpan == null || CurrentSpan.Snapshot != span.Snapshot)
+ {
+ CurrentSpan = new SnapshotSpan(span.Snapshot, 0, span.Snapshot.Length);
+ }
+
+ IList classifiedSpans = new List();
+
+ var tags = Tagger.GetTags(span);
+
+ foreach (IMappingTagSpan tagSpan in tags)
+ {
+ var validationSpan = tagSpan.Span.GetSpans(span.Snapshot).First();
+ classifiedSpans.Add(new ClassificationSpan(validationSpan, ClassificationType));
+ }
+
+ return classifiedSpans;
+ }
+
+ ///
+ /// Create an event for when the Classification changes
+ ///
+ public event EventHandler ClassificationChanged;
+
+ ///
+ /// Force refresh a span stored on last update (assume it corresponds to currently active document)
+ ///
+ public void Invalidate()
+ {
+ ClassificationChanged?.Invoke(this, new ClassificationChangedEventArgs(CurrentSpan));
+ }
+
+ static public void InvalidateActiveClassifier()
+ {
+ if (ActiveClassifier != null)
+ ActiveClassifier.Invalidate();
+ }
+ }
+}
Index: clang-tidy-vs/ClangTidy/ClassifierAndTagger/ClassifierProvider.cs
===================================================================
--- /dev/null
+++ clang-tidy-vs/ClangTidy/ClassifierAndTagger/ClassifierProvider.cs
@@ -0,0 +1,55 @@
+´╗┐using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Utilities;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Text;
+using System.Windows.Media;
+
+namespace LLVM.ClangTidy
+{
+ ///
+ /// This class creates Classifier that will search for clang-tidy validation warnings in the
+ /// visible text. Results will be highlighted in code using ValidationWarningFormat classification.
+ /// Export a
+ ///
+ [Export(typeof(IClassifierProvider))]
+ [ContentType("code")]
+ internal class ClassifierProvider : IClassifierProvider
+ {
+ [Export(typeof(ClassificationTypeDefinition))]
+ [Name("clang-tidy-validation")]
+ internal ClassificationTypeDefinition ValidationClassificationType = null;
+
+ [Import]
+ internal IClassificationTypeRegistryService ClassificationRegistry = null;
+
+ [Import]
+ internal IBufferTagAggregatorFactoryService TagAggregatorFactory = null;
+
+ public IClassifier GetClassifier(ITextBuffer buffer)
+ {
+ IClassificationType classificationType = ClassificationRegistry.GetClassificationType("clang-tidy-validation");
+
+ var tagAggregator = TagAggregatorFactory.CreateTagAggregator(buffer);
+ return new Classifier(tagAggregator, classificationType);
+ }
+ }
+
+ ///
+ /// Set the display values for the classification
+ ///
+ [Export(typeof(EditorFormatDefinition))]
+ [ClassificationType(ClassificationTypeNames = "clang-tidy-validation")]
+ [Name("clang-tidy validation")]
+ [UserVisible(false)]
+ [Order(After = Priority.High)]
+ internal sealed class ValidationWarningFormat : ClassificationFormatDefinition
+ {
+ public ValidationWarningFormat()
+ {
+ DisplayName = "clang-tidy validation failed";
+ BackgroundOpacity = 0.3f;
+ BackgroundColor = Colors.Red;
+ }
+ }
+}
Index: clang-tidy-vs/ClangTidy/ClassifierAndTagger/QuickInfoController.cs
===================================================================
--- /dev/null
+++ clang-tidy-vs/ClangTidy/ClassifierAndTagger/QuickInfoController.cs
@@ -0,0 +1,76 @@
+´╗┐using System.Collections.Generic;
+using Microsoft.VisualStudio.Language.Intellisense;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+
+namespace LLVM.ClangTidy
+{
+ ///
+ /// This class allows augmentations of Intellisense quick info when
+ /// a user hovers his mouse over one of clang-tidy validation warnings in code.
+ /// Quick info content augmentations are performed in QuickInfoSource.
+ ///
+ internal class QuickInfoController : IIntellisenseController
+ {
+ private ITextView TextView;
+ private IList SubjectBuffers;
+ private QuickInfoControllerProvider Provider;
+ private IQuickInfoSession Session;
+
+ internal QuickInfoController(ITextView textView, IList subjectBuffers, QuickInfoControllerProvider provider)
+ {
+ TextView = textView;
+ SubjectBuffers = subjectBuffers;
+ Provider = provider;
+
+ TextView.MouseHover += OnTextViewMouseHover;
+ }
+
+ private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e)
+ {
+ SnapshotPoint? point = GetMousePosition(new SnapshotPoint(TextView.TextSnapshot, e.Position));
+
+ if (point != null)
+ {
+ ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position,
+ PointTrackingMode.Positive);
+
+ // Find the broker for this buffer
+ if (!Provider.QuickInfoBroker.IsQuickInfoActive(TextView))
+ {
+ Session = Provider.QuickInfoBroker.CreateQuickInfoSession(TextView, triggerPoint, true);
+ Session.Start();
+ }
+ }
+ }
+
+ public void Detach(ITextView textView)
+ {
+ if (TextView == textView)
+ {
+ TextView.MouseHover -= this.OnTextViewMouseHover;
+ TextView = null;
+ }
+ }
+
+ private SnapshotPoint? GetMousePosition(SnapshotPoint topPosition)
+ {
+ // Map this point down to the appropriate subject buffer.
+ return TextView.BufferGraph.MapDownToFirstMatch
+ (
+ topPosition,
+ PointTrackingMode.Positive,
+ snapshot => SubjectBuffers.Contains(snapshot.TextBuffer),
+ PositionAffinity.Predecessor
+ );
+ }
+
+ public void ConnectSubjectBuffer(ITextBuffer subjectBuffer)
+ {
+ }
+
+ public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer)
+ {
+ }
+ }
+}
Index: clang-tidy-vs/ClangTidy/ClassifierAndTagger/QuickInfoControllerProvider.cs
===================================================================
--- /dev/null
+++ clang-tidy-vs/ClangTidy/ClassifierAndTagger/QuickInfoControllerProvider.cs
@@ -0,0 +1,28 @@
+´╗┐using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Language.Intellisense;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Utilities;
+
+namespace LLVM.ClangTidy
+{
+ ///
+ /// This class creates QuickInfoControllerProvider to be used for
+ /// augmenting Intellisense quick info when hovering over clang-tidy
+ /// validation warnings in code.
+ ///
+ [Export(typeof(IIntellisenseControllerProvider))]
+ [Name("ClangTidy QuickInfo Controller")]
+ [ContentType("text")]
+ internal class QuickInfoControllerProvider : IIntellisenseControllerProvider
+ {
+ [Import]
+ internal IQuickInfoBroker QuickInfoBroker { get; set; }
+
+ public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList subjectBuffers)
+ {
+ return new QuickInfoController(textView, subjectBuffers, this);
+ }
+ }
+}
Index: clang-tidy-vs/ClangTidy/ClassifierAndTagger/QuickInfoSource.cs
===================================================================
--- /dev/null
+++ clang-tidy-vs/ClangTidy/ClassifierAndTagger/QuickInfoSource.cs
@@ -0,0 +1,57 @@
+´╗┐using System;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.Language.Intellisense;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Tagging;
+using System.Linq;
+
+namespace LLVM.ClangTidy
+{
+ ///
+ /// This class searches for clang-tidy validation warnings (implicitly using
+ /// ValidationTagger's functionality) in a text span provided by QuickInfoController.
+ /// Results are augmented for Intellisense quick info using the message stored in
+ /// ValidationTag by ValidationTagger.
+ ///
+ internal class QuickInfoSource : IQuickInfoSource
+ {
+ private ITagAggregator Aggregator;
+ private ITextBuffer Buffer;
+ private bool IsDisposed = false;
+
+ public QuickInfoSource(ITextBuffer buffer, ITagAggregator aggregator)
+ {
+ Aggregator = aggregator;
+ Buffer = buffer;
+ }
+
+ public void AugmentQuickInfoSession(IQuickInfoSession session, IList