diff --git a/ClangPowerTools/ClangPowerToolsShared/MVVM/Models/TidySettingsModel.cs b/ClangPowerTools/ClangPowerToolsShared/MVVM/Models/TidySettingsModel.cs
index 0d5d9f8ef..e5960c5df 100644
--- a/ClangPowerTools/ClangPowerToolsShared/MVVM/Models/TidySettingsModel.cs
+++ b/ClangPowerTools/ClangPowerToolsShared/MVVM/Models/TidySettingsModel.cs
@@ -11,7 +11,7 @@ public class TidySettingsModel
public string CustomChecks { get; set; } = string.Empty;
public string CustomExecutable { get; set; } = string.Empty;
-
+ public string CompilationDatabase { get; set; } = string.Empty;
public bool DetectClangTidyFile { get; set; } = true;
public bool FormatAfterTidy { get; set; } = false;
diff --git a/ClangPowerTools/ClangPowerToolsShared/MVVM/SettingsTooltips.cs b/ClangPowerTools/ClangPowerToolsShared/MVVM/SettingsTooltips.cs
index 03837c0e9..c5bbb88c3 100644
--- a/ClangPowerTools/ClangPowerToolsShared/MVVM/SettingsTooltips.cs
+++ b/ClangPowerTools/ClangPowerToolsShared/MVVM/SettingsTooltips.cs
@@ -30,6 +30,7 @@ public class SettingsTooltips
public string PredefinedChecks { get; } = "A list of clang-tidy static analyzer and diagnostics checks from LLVM.";
public string CustomChecks { get; } = "Specify clang-tidy checks to run using the standard tidy syntax. You can use wildcards to match multiple checks, combine them, etc (Eg. \"modernize-*, readability-*\").";
public string CustomExecutableTidy { get; } = "Specify a custom path for \"clang-tidy.exe\" file to run instead of the built-in one (v8.0).";
+ public string CompilationDatabase{ get; } = "Specify a custom \"compile_commands.json\" file path to use as a source of compilation flags instead of the flags generated by extension.";
public string DetectClangTidyFile { get; } = "Automatically detect the \".clang-tidy\" file and set the \"Use checks from\" option to \"TidyFile\" if the file exists. Otherwise, set the \"Use checks from\" option to \"PredefinedChecks\".";
public string FormatAfterTidy { get; } = "Automatically run clang-format after clang-tidy finished.";
public string TidyOnSave { get; } = "Automatically run clang-tidy when saving the current source file.";
diff --git a/ClangPowerTools/ClangPowerToolsShared/MVVM/ViewModels/TidySettingsViewModel.cs b/ClangPowerTools/ClangPowerToolsShared/MVVM/ViewModels/TidySettingsViewModel.cs
index 440eefc2e..010cfcbdf 100644
--- a/ClangPowerTools/ClangPowerToolsShared/MVVM/ViewModels/TidySettingsViewModel.cs
+++ b/ClangPowerTools/ClangPowerToolsShared/MVVM/ViewModels/TidySettingsViewModel.cs
@@ -21,6 +21,7 @@ public class TidySettingsViewModel : CommonSettingsFunctionality, INotifyPropert
private string displayWarning = string.Empty;
private ICommand headerFilterAddDataCommand;
private ICommand customExecutableBrowseCommand;
+ private ICommand compilationDatabaseBrowseCommand;
private ICommand predefinedChecksSelectCommand;
private ICommand customChecksAddDataCommand;
private ICommand exportTidyConfigCommand;
@@ -118,6 +119,11 @@ public ICommand CustomExecutableBrowseCommand
get => customExecutableBrowseCommand ?? (customExecutableBrowseCommand = new RelayCommand(() => UpdateCustomExecutable(), () => CanExecute));
}
+ public ICommand CompilationDatabaseBrowseCommand
+ {
+ get => compilationDatabaseBrowseCommand ?? (compilationDatabaseBrowseCommand = new RelayCommand(() => UpdateCompilationDatabase(), () => CanExecute));
+ }
+
public ICommand PredefinedChecksSelectCommand
{
get => predefinedChecksSelectCommand ?? (predefinedChecksSelectCommand = new RelayCommand(() => UpdatePredefinedChecks(), () => CanExecute));
@@ -167,6 +173,16 @@ private void UpdateCustomExecutable()
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TidyModel"));
}
+ private void UpdateCompilationDatabase()
+ {
+ string path = OpenFile(string.Empty, ".json", "Compilation database (*.json)|*.json");
+ if (string.IsNullOrEmpty(path) == false)
+ {
+ tidyModel.CompilationDatabase = path;
+ }
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TidyModel"));
+ }
+
private void UpdatePredefinedChecks()
{
OpenChecksWindow();
diff --git a/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/Styles/ImageResources.xaml b/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/Styles/ImageResources.xaml
index 31e926055..8837595c2 100644
--- a/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/Styles/ImageResources.xaml
+++ b/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/Styles/ImageResources.xaml
@@ -8,6 +8,7 @@
+
diff --git a/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/TidySettingsView.xaml b/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/TidySettingsView.xaml
index dc2ac0a79..664a56a47 100644
--- a/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/TidySettingsView.xaml
+++ b/ClangPowerTools/ClangPowerToolsShared/MVVM/Views/TidySettingsView.xaml
@@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ClangPowerTools"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- d:DesignHeight="420"
+ d:DesignHeight="440"
d:DesignWidth="770"
mc:Ignorable="d">
@@ -217,8 +217,49 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
@@ -330,7 +371,7 @@
-
+
/// The clang flags
- private string GetClangFlags()
+ private string GetClangFlagsOption()
{
var compilerSettings = SettingsProvider.CompilerSettingsModel;
@@ -182,17 +182,21 @@ private string GetTidyParameters()
using FileStream fs = new FileStream(filePath, FileMode.Create);
using StreamWriter sw = new StreamWriter(fs);
sw.Write(text);
- parameters = AppendClangTidyType(filePath);
+ parameters = AppendClangTidyTypeOption(filePath);
}
else
{
- parameters = AppendClangTidyType(parameters);
+ parameters = AppendClangTidyTypeOption(parameters);
}
}
// Get the header filter option
- if (null != tidySettings.HeaderFilter && !string.IsNullOrWhiteSpace(tidySettings.HeaderFilter))
- parameters += $" {GetHeaderFilters()}";
+ if (!string.IsNullOrWhiteSpace(tidySettings.HeaderFilter))
+ parameters += $" {GetHeaderFiltersOption()}";
+
+ // Get the compilation database option
+ if (!string.IsNullOrWhiteSpace(tidySettings.CompilationDatabase))
+ parameters += $" {GetCompilationDatabaseOption(tidySettings.CompilationDatabase)}";
parameters += $" {ScriptConstants.kParallel}";
return parameters;
@@ -204,7 +208,7 @@ private string GetTidyParameters()
///
///
/// The <"aParameters"> value with the clang tidy type with / without the clang tidy config file option attached
- private string AppendClangTidyType(string aParameters)
+ private string AppendClangTidyTypeOption(string aParameters)
{
return string.Format("{0} '{1}'",
(CommandIds.kTidyFixId == mCommandId ? ScriptConstants.kTidyFix : ScriptConstants.kTidy),
@@ -216,7 +220,7 @@ private string AppendClangTidyType(string aParameters)
/// Get the header filter option from the Clang Tidy Option page
///
/// Header filter option
- private string GetHeaderFilters()
+ private string GetHeaderFiltersOption()
{
var tidySettings = SettingsProvider.TidySettingsModel;
@@ -244,6 +248,15 @@ private string GetTidyChecks(TidySettingsModel tidyModel)
}
}
+ ///
+ /// Get the compilation database file option from the Clang Tidy Option page
+ ///
+ /// Compilation database file option
+ private string GetCompilationDatabaseOption(string compilationDatabase)
+ {
+ DirectoryInfo dbPath = new DirectoryInfo(compilationDatabase);
+ return string.Format("{0} '{1}'", ScriptConstants.kCompilationDatabaseDir, dbPath.Parent.FullName);
+ }
#endregion
diff --git a/ClangPowerTools/ClangPowerToolsShared/Script/ScriptConstants.cs b/ClangPowerTools/ClangPowerToolsShared/Script/ScriptConstants.cs
index bb7b0aad3..32e34d3ef 100644
--- a/ClangPowerTools/ClangPowerToolsShared/Script/ScriptConstants.cs
+++ b/ClangPowerTools/ClangPowerToolsShared/Script/ScriptConstants.cs
@@ -110,6 +110,7 @@ public class ScriptConstants
public const string kHeaderFilter = "-header-filter";
public const string kTidyFile = ".clang-tidy";
+ public const string kCompilationDatabaseDir = "-compilation-database-dir";
public const string kClangFormatStyle = "-format-style";
diff --git a/ClangPowerTools/ClangPowerToolsShared/Tooling/v1/clang-build.ps1 b/ClangPowerTools/ClangPowerToolsShared/Tooling/v1/clang-build.ps1
index 646d13fc4..fb61b4414 100644
--- a/ClangPowerTools/ClangPowerToolsShared/Tooling/v1/clang-build.ps1
+++ b/ClangPowerTools/ClangPowerToolsShared/Tooling/v1/clang-build.ps1
@@ -172,6 +172,10 @@ param( [alias("proj")]
[Parameter(Mandatory=$false, HelpMessage="Enable Clang-Tidy to run on header files")]
[string] $aTidyHeaderFilter
+ , [alias("compilation-database-dir")]
+ [Parameter(Mandatory=$false, HelpMessage="Specify a path of a directory where compile_commands.json is located.")]
+ [string] $aCompilationDatabaseDir
+
, [alias("format-style")]
[Parameter(Mandatory=$false, HelpMessage="Used with 'tidy-fix'; tells CLANG TIDY-FIX to also format the fixed file(s)")]
[string] $aAfterTidyFixFormatStyle
@@ -240,12 +244,14 @@ Set-Variable -name kClangTidyFixExportFixes -value "--export-fixes=" -option
Set-Variable -name kClangCompiler -value "clang++.exe" -option Constant
-Set-Variable -name kClangTidyFlags -value @("-quiet"
- ,"--") -option Constant
+Set-Variable -name kQuiet -value '-quiet' -option Constant
+Set-Variable -name kEndOptionMarker -value "--" -option Constant
+
Set-Variable -name kClangTidyFlagHeaderFilter -value "-header-filter=" -option Constant
Set-Variable -name kClangTidyFlagChecks -value "-checks=" -option Constant
Set-Variable -name kClangTidyUseFile -value ".clang-tidy" -option Constant
Set-Variable -name kClangTidyFormatStyle -value "-format-style=" -option Constant
+Set-Variable -name kClangTidyCompilationDatabaseDir -value "-p=" -option Constant
Set-Variable -name kClangTidyFlagTempFile -value ""
@@ -826,7 +832,8 @@ Function Get-TidyCallArguments( [Parameter(Mandatory=$false)][string[]] $preproc
, [Parameter(Mandatory=$false)][string[]] $forceIncludeFiles
, [Parameter(Mandatory=$true)][string] $fileToTidy
, [Parameter(Mandatory=$false)][string] $pchFilePath
- , [Parameter(Mandatory=$false)][switch] $fix)
+ , [Parameter(Mandatory=$false)][switch] $fix
+ , [Parameter(Mandatory=$false)][string] $compilationDatabaseDir)
{
[string[]] $tidyArgs = @()
if ($fix)
@@ -864,7 +871,21 @@ Function Get-TidyCallArguments( [Parameter(Mandatory=$false)][string[]] $preproc
}
}
- $tidyArgs += $kClangTidyFlags
+ $tidyArgs += $kQuiet
+ if (![string]::IsNullOrEmpty($compilationDatabaseDir))
+ {
+ if ($compilationDatabaseDir -eq '_')
+ {
+ $compilationDatabaseDir = Get-SourceDirectory
+ }
+ # When passed to cmd.exe the quote cannot be preceded by a backslash or it's escaped
+ $tidyArgs += "$kClangTidyCompilationDatabaseDir`"$($compilationDatabaseDir.TrimEnd("\"))`""
+ # When we use compilation database, we don't need to add further args with
+ # compilation flags
+ return $tidyArgs
+ }
+
+ $tidyArgs += $kEndOptionMarker
$tidyArgs += Get-ClangIncludeDirectories -includeDirectories $includeDirectories `
-additionalIncludeDirectories $additionalIncludeDirectories
@@ -900,7 +921,8 @@ Function Get-ExeCallArguments( [Parameter(Mandatory=$false)][string] $pchF
, [Parameter(Mandatory=$false)][string[]] $preprocessorDefinitions
, [Parameter(Mandatory=$false)][string[]] $forceIncludeFiles
, [Parameter(Mandatory=$true) ][string] $currentFile
- , [Parameter(Mandatory=$true) ][WorkloadType] $workloadType)
+ , [Parameter(Mandatory=$true) ][WorkloadType] $workloadType
+ , [Parameter(Mandatory=$false)][string] $compilationDatabaseDir)
{
switch ($workloadType)
{
@@ -915,13 +937,15 @@ Function Get-ExeCallArguments( [Parameter(Mandatory=$false)][string] $pchF
-additionalIncludeDirectories $additionalIncludeDirectories `
-forceIncludeFiles $forceIncludeFiles `
-pchFilePath $pchFilePath `
- -fileToTidy $currentFile }
+ -fileToTidy $currentFile `
+ -compilationDatabaseDir $compilationDatabaseDir}
TidyFix { return Get-TidyCallArguments -preprocessorDefinitions $preprocessorDefinitions `
-includeDirectories $includeDirectories `
-additionalIncludeDirectories $additionalIncludeDirectories `
-forceIncludeFiles $forceIncludeFiles `
-pchFilePath $pchFilePath `
-fileToTidy $currentFile `
+ -compilationDatabaseDir $compilationDatabaseDir `
-fix}
}
}
@@ -1005,17 +1029,20 @@ Function Run-ClangJobs( [Parameter(Mandatory=$true)] $clangJobs
[string] $clangConfigContent = ""
if ($job.FilePath -like '*tidy*')
{
- # We have to separate Clang args from Tidy args
- $splitparams = $job.ArgumentList -split " -- "
- $clangConfigContent = $splitparams[1]
-
- # We may have an explicit .clang-tidy check-flag config file to be used
- if (![string]::IsNullOrWhiteSpace($job.TidyFlagsTempFile) -and (Test-Path -LiteralPath $job.TidyFlagsTempFile))
+ if (!($job.ArgumentList -like "$($job.kClangTidyCompilationDatabaseDir)*"))
{
- $splitparams[0] += " --config-file=""$($job.TidyFlagsTempFile)"" "
- }
+ # We have to separate Clang args from Tidy args
+ $splitparams = $job.ArgumentList -split " -- "
+ $clangConfigContent = $splitparams[1]
- $job.ArgumentList = "$($splitparams[0]) -- --config ""$clangConfigFile"""
+ # We may have an explicit .clang-tidy check-flag config file to be used
+ if (![string]::IsNullOrWhiteSpace($job.TidyFlagsTempFile) -and (Test-Path -LiteralPath $job.TidyFlagsTempFile))
+ {
+ $splitparams[0] += " --config-file=""$($job.TidyFlagsTempFile)"" "
+ }
+
+ $job.ArgumentList = "$($splitparams[0]) -- --config ""$clangConfigFile"""
+ }
}
else
{
@@ -1034,7 +1061,6 @@ Function Run-ClangJobs( [Parameter(Mandatory=$true)] $clangJobs
# When PowerShell encounters errors, the first one is handled differently from consecutive ones
# To circumvent this, do not execute the job directly, but execute it via cmd.exe
# See also https://stackoverflow.com/a/35980675
-
$callOutput = cmd /c "$($job.FilePath) $($job.ArgumentList) 2>&1" | Out-String
$callSuccess = $LASTEXITCODE -eq 0
@@ -1550,7 +1576,8 @@ Function Process-Project( [Parameter(Mandatory=$true)] [string] $vcxprojPa
-forceIncludeFiles $cppForceIncludes `
-currentFile $cpp `
-includeDirectories $includeDirectories `
- -additionalIncludeDirectories $additionalIncludeDirectories
+ -additionalIncludeDirectories $additionalIncludeDirectories `
+ -compilationDatabaseDir $aCompilationDatabaseDir
$newJob = New-Object PsObject -Prop @{ 'FilePath' = $exeToCall
; 'WorkingDirectory' = Get-SourceDirectory
@@ -1558,6 +1585,7 @@ Function Process-Project( [Parameter(Mandatory=$true)] [string] $vcxprojPa
; 'File' = $cpp
; 'JobCounter' = 0 <# will be lazy initialized #>
; 'TidyFlagsTempFile' = $kClangTidyFlagTempFile
+ ; 'kClangTidyCompilationDatabaseDir' = $kClangTidyCompilationDatabaseDir
}
$clangJobs += $newJob
}