Skip to content
Go to file
Cannot retrieve contributors at this time
167 lines (144 sloc) 7.08 KB
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Mono.Options;
namespace RCLTStarter
class InspectCodeRunner
string m_BaseDir;
string m_OutPutFilePath;
string m_PluginsInstallDir;
List<string> m_InspectCodeOptions;
const string k_SdkVersion = "2018.1.0";
List<string> m_PluginsSpecifiedInCommandLine;
string m_CachesHome;
public InspectCodeRunner(string[] args)
m_PluginsSpecifiedInCommandLine = new List<string>();
var options = new OptionSet {
{ "base-dir=", "Consist of two folders: 1. JetBrains.ReSharper.CommandLineTools with tools executable. 'packages' contains code analysis packages", v => m_BaseDir = v },
{ "o=|output=", "Files contains 'inspectcode' output. Default: $base-dir\\result.xml", v => m_OutPutFilePath = v },
{ "p=|plugin=", $"Plugin id with version. E.g 'ReSharper.FooDetector.2018.0.1'. If version part is not specified, {k_SdkVersion} is used.", v => m_PluginsSpecifiedInCommandLine.Add(v)}
m_InspectCodeOptions = options.Parse(args);
if (string.IsNullOrEmpty(m_BaseDir))
m_BaseDir = Environment.CurrentDirectory;
m_BaseDir = Path.GetFullPath(m_BaseDir);
if (string.IsNullOrEmpty(m_OutPutFilePath))
m_OutPutFilePath = Path.Combine(m_BaseDir, "result.xml");
// Use unique location for cache, otherwise 'inspectcode' might not pickup newly installed plugins
m_CachesHome = GetTemporaryDirectory();
m_PluginsInstallDir = Path.Combine(m_BaseDir, "Plugins");
public void Run()
// After installation is complete inspectcode.exe located in base_dir\JetBrains.ReSharper.CommandLineTools\tools\inspectcode.exe
// Uses NuGet to install packages to base_dir\Plugins
var codeAnalysisPlugins = InstallCodeAnalysisPlugins();
// Runs 'inspectcode.exe' on specified project or solution.
// Look for comments inside 'SetupAdditionalDeployerPackagesEnvVar' for extra details
void DeleteTemporaryCacheFolder()
Console.WriteLine($"Deleting temporary cache folder {m_CachesHome}");
Directory.Delete(m_CachesHome, true);
private void InstallReSharperCommandLineTools()
var sources = new[] { "" };
var installer = new NuGetPackagesInstaller(sources, m_BaseDir);
var packages = new[]
new PackageInfo { Id = "JetBrains.ReSharper.CommandLineTools", Version = k_SdkVersion},
private List<string> InstallCodeAnalysisPlugins()
var sources = new[] { "", "" };
var packages = new List<PackageInfo>();
foreach (var p in m_PluginsSpecifiedInCommandLine)
var match = Regex.Match(p, @"\d+(\s*\.\s*\d+){0,3}$");
if (match.Success)
var version = match.Groups[0].Value;
packages.Add(new PackageInfo { Id = p.Remove(p.LastIndexOf(version) - 1), Version = version });
packages.Add(new PackageInfo { Id = p, Version = k_SdkVersion});
var installer = new NuGetPackagesInstaller(sources, m_PluginsInstallDir);
return installer.InstallPackages(packages);
private void SetupAdditionalDeployerPackagesEnvVar(List<string> installedPackages)
Forms XML and writes it `JET_ADDITIONAL_DEPLOYED_PACKAGES` environment variable.
Each 'Folder' contains a path to an expanded NuGet package
<Folder Path="c:\RCLTTest\ReSharper.FooDetector" />
<Folder Path="c:\RCLTTest\PowerToys.CyclomaticComplexity" />
See documentation JetBrains.Application.Environment.AdditionalDeployedPackages.Schema
in 'JetBrains.ReSharper.CommandLineTools\tools\JetBrains.Platform.Shell.xml'
Using 'Folder' was the only way I could make it work. It is possible to use 'File' element,
but it requires writing code for downloading `nupukg` instead of utilizing the power of NuGet caching.
Other options are described in `JetBrains.Platform.Shell.xml` like Download-Id.
Each 'Folder' contains an expanded package content and a nupkg file. However,
`inspectcode` ignores expanded package content; instead, it picks up a nupkg and expands
it somewhere into [folder_name]. I would expect 'inspectcode' to use package content which already
expanded to 'Folder'. I’ve left a request to fix it here
When/if it is fixed, the overhead will disappear.
var doc = new XmlDocument();
var packages = doc.CreateElement("Packages");
foreach (var packageRelativePath in installedPackages)
var folder = doc.CreateElement("Folder");
folder.SetAttribute("Path", Path.Combine(m_PluginsInstallDir, packageRelativePath));
var sb = new StringBuilder();
var tw = new StringWriter(sb);
Environment.SetEnvironmentVariable("JET_ADDITIONAL_DEPLOYED_PACKAGES", sb.ToString());
private void RunInspectCode(List<string> installedPlugins)
var inspectCode = Path.Combine(m_BaseDir, "JetBrains.ReSharper.CommandLineTools", "tools", "inspectcode.exe");
var p = Process.Start(inspectCode, string.Join(" ", m_InspectCodeOptions));
if (p == null)
throw new Exception("failed to start inspectcode.exe");
private static string GetTemporaryDirectory()
var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
return tempDirectory;
You can’t perform that action at this time.