public void RoslynPlugin_GenerateForDependencyAnalyzers_Succeeds() { // Arrange TestLogger logger = new TestLogger(); string outputDir = TestUtils.CreateTestDirectory(this.TestContext, ".out"); string dummyContentFile = TestUtils.CreateTextFile("dummy.txt", outputDir, "non-analyzer content file"); // Create a valid analyzer package RoslynAnalyzer11.CSharpAnalyzer analyzer = new RoslynAnalyzer11.CSharpAnalyzer(); string fakeRemoteNuGetDir = TestUtils.CreateTestDirectory(this.TestContext, ".fakeRemoteNuGet"); IPackageManager fakeRemotePkgMgr = CreatePackageManager(fakeRemoteNuGetDir); IPackage child1 = AddPackage(fakeRemotePkgMgr, "Analyzer.Child1", "1.1.0", analyzer.GetType().Assembly.Location); IPackage child2 = AddPackage(fakeRemotePkgMgr, "Analyzer.Child2", "1.2.0", analyzer.GetType().Assembly.Location); IPackage targetPkg = AddPackage(fakeRemotePkgMgr, "Empty.Parent", "1.0.0", dummyContentFile, child1, child2); string localPackageDestination = TestUtils.CreateTestDirectory(this.TestContext, ".localpackages"); // Act NuGetPackageHandler nuGetHandler = new NuGetPackageHandler(fakeRemotePkgMgr.LocalRepository, localPackageDestination, logger); AnalyzerPluginGenerator apg = new AnalyzerPluginGenerator(nuGetHandler, logger); ProcessedArgs args = new ProcessedArgs(targetPkg.Id, targetPkg.Version, "cs", null, false, true /* generate plugins for dependencies with analyzers*/, outputDir); bool result = apg.Generate(args); // Assert Assert.IsTrue(result); // Expecting one plugin per dependency with analyzers CheckJarGeneratedForPackage(outputDir, analyzer, child1); CheckJarGeneratedForPackage(outputDir, analyzer, child2); AssertJarsGenerated(outputDir, 2); }
public ProcessedArgs Process(string[] commandLineArgs) { ProcessedArgs processed = null; IEnumerable<ArgumentInstance> arguments; // This call will fail if there are duplicate, missing, or unrecognized arguments CommandLineParser parser = new CommandLineParser(Descriptors, false /* don't allow unrecognized */); bool parsedOk = parser.ParseArguments(commandLineArgs, this.logger, out arguments); NuGetReference analyzerRef; parsedOk &= TryParseAnalyzerRef(arguments, out analyzerRef); string sqaleFilePath; parsedOk &= TryParseSqaleFile(arguments, out sqaleFilePath); if (parsedOk) { Debug.Assert(analyzerRef != null, "Expecting to have a valid analyzer reference"); processed = new ProcessedArgs(analyzerRef, sqaleFilePath); } return processed; }
private static ProcessedArgs CreateArgs(string packageId, string packageVersion, string language, string sqaleFilePath, bool acceptLicenses, string outputDirectory) { ProcessedArgs args = new ProcessedArgs( packageId, new SemanticVersion(packageVersion), language, sqaleFilePath, acceptLicenses, outputDirectory); return args; }
public void RoslynPlugin_GenerateForValidAnalyzer_Succeeds() { // Arrange TestLogger logger = new TestLogger(); string outputDir = TestUtils.CreateTestDirectory(this.TestContext, ".out"); // Create a valid analyzer package RoslynAnalyzer11.CSharpAnalyzer analyzer = new RoslynAnalyzer11.CSharpAnalyzer(); string packageId = "Analyzer1.Pkgid1"; // package id is not all lowercase string fakeRemoteNuGetDir = TestUtils.CreateTestDirectory(this.TestContext, ".fakeRemoteNuGet"); IPackageManager fakeRemotePkgMgr = CreatePackageManager(fakeRemoteNuGetDir); IPackage analyzerPkg = AddPackage(fakeRemotePkgMgr, packageId, "1.0.2", analyzer.GetType().Assembly.Location); string localPackageDestination = TestUtils.CreateTestDirectory(this.TestContext, ".localpackages"); // Act NuGetPackageHandler nuGetHandler = new NuGetPackageHandler(fakeRemotePkgMgr.LocalRepository, localPackageDestination, logger); AnalyzerPluginGenerator apg = new AnalyzerPluginGenerator(nuGetHandler, logger); ProcessedArgs args = new ProcessedArgs(packageId, new SemanticVersion("1.0.2"), "cs", null, false, false, outputDir); bool result = apg.Generate(args); // Assert Assert.IsTrue(result); // Expecting one plugin per dependency with analyzers CheckJarGeneratedForPackage(outputDir, analyzer, analyzerPkg); AssertJarsGenerated(outputDir, 1); }
private static void AssertArgumentsNotProcessed(ProcessedArgs actualArgs, TestLogger logger) { Assert.IsNull(actualArgs, "Not expecting the arguments to have been processed successfully"); logger.AssertErrorsLogged(); }
private static void AssertArgumentsProcessed(ProcessedArgs actualArgs, TestLogger logger, string expectedId, string expectedVersion, string expectedSqale, bool expectedAcceptLicenses) { Assert.IsNotNull(actualArgs, "Expecting the arguments to have been processed successfully"); Assert.AreEqual(actualArgs.PackageId, expectedId, "Unexpected package id returned"); if (expectedVersion == null) { Assert.IsNull(actualArgs.PackageVersion, "Expecting the version to be null"); } else { Assert.IsNotNull(actualArgs.PackageVersion, "Not expecting the version to be null"); Assert.AreEqual(expectedVersion, actualArgs.PackageVersion.ToString()); } Assert.AreEqual(expectedSqale, actualArgs.SqaleFilePath, "Unexpected sqale file path"); if (expectedSqale != null) { Assert.IsTrue(File.Exists(expectedSqale), "Specified sqale file should exist: {0}", expectedSqale); } Assert.AreEqual(expectedAcceptLicenses, actualArgs.AcceptLicenses, "Unexpected value for AcceptLicenses"); logger.AssertErrorsLogged(0); }
public void RoslynPlugin_GenerateForValidAnalyzer_Succeeds() { // Arrange TestLogger logger = new TestLogger(); string outputDir = TestUtils.CreateTestDirectory(this.TestContext, ".out"); // Create a valid analyzer package RoslynAnalyzer11.CSharpAnalyzer analyzer = new RoslynAnalyzer11.CSharpAnalyzer(); string packageId = "Analyzer1.Pkgid1"; // package id is not all lowercase string fakeRemoteNuGetDir = TestUtils.CreateTestDirectory(this.TestContext, ".fakeRemoteNuGet"); IPackageManager fakeRemotePkgMgr = CreatePackageManager(fakeRemoteNuGetDir); IPackage analyzerPkg = AddPackage(fakeRemotePkgMgr, packageId, "1.0.2", analyzer.GetType().Assembly.Location); string localPackageDestination = TestUtils.CreateTestDirectory(this.TestContext, ".localpackages"); // Act NuGetPackageHandler nuGetHandler = new NuGetPackageHandler(fakeRemotePkgMgr.LocalRepository, localPackageDestination, logger); AnalyzerPluginGenerator apg = new AnalyzerPluginGenerator(nuGetHandler, logger); ProcessedArgs args = new ProcessedArgs(packageId, new SemanticVersion("1.0.2"), "cs", null, false, outputDir); bool result = apg.Generate(args); // Assert Assert.IsTrue(result); string jarFilePath = AssertPluginJarExists(outputDir); // Check the content of the files embedded in the jar ZipFileChecker jarChecker = new ZipFileChecker(this.TestContext, jarFilePath); // Check the contents of the embedded config file string embeddedConfigFile = jarChecker.AssertFileExists("org\\sonar\\plugins\\roslynsdk\\configuration.xml"); RoslynSdkConfiguration config = RoslynSdkConfiguration.Load(embeddedConfigFile); // Check the config settings Assert.AreEqual("analyzer1pkgid1", config.PluginKeyDifferentiator, "Unexpected repository differentiator"); Assert.AreEqual("roslyn.analyzer1.pkgid1.cs", config.RepositoryKey, "Unexpected repository key"); Assert.AreEqual("cs", config.RepositoryLanguage, "Unexpected language"); Assert.AreEqual("dummy title", config.RepositoryName, "Unexpected repository name"); // Check for the expected property values required by the C# plugin // Property name prefixes should be lower case; the case of the value should be the same as the package id AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.analyzerId", "Analyzer1.Pkgid1", config); AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.ruleNamespace", "Analyzer1.Pkgid1", config); AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.nuget.packageId", "Analyzer1.Pkgid1", config); AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.nuget.packageVersion", "1.0.2", config); AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.staticResourceName", "Analyzer1.Pkgid1.1.0.2.zip", config); AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.pluginKey", "analyzer1pkgid1", config); AssertExpectedPropertyDefinitionValue("analyzer1.pkgid1.cs.pluginVersion", "1.0.2", config); // Check the contents of the manifest string actualManifestFilePath = jarChecker.AssertFileExists("META-INF\\MANIFEST.MF"); string[] actualManifest = File.ReadAllLines(actualManifestFilePath); AssertExpectedManifestValue(WellKnownPluginProperties.Key, "analyzer1pkgid1", actualManifest); AssertExpectedManifestValue("Plugin-Key", "analyzer1pkgid1", actualManifest); // plugin-key should be lowercase and alphanumeric AssertPackagePropertiesInManifest(analyzerPkg, actualManifest); // Check the rules string actualRuleFilePath = jarChecker.AssertFileExists("." + config.RulesXmlResourcePath); AssertExpectedRulesExist(analyzer, actualRuleFilePath); // Now create another checker to check the contents of the zip file (strict check this time) CheckEmbeddedAnalyzerPayload(jarChecker, "static\\analyzer1.pkgid1.1.0.2.zip", /* zip file contents */ "analyzers\\RoslynAnalyzer11.dll"); }
public bool Generate(ProcessedArgs args) { if (args == null) { throw new ArgumentNullException("args"); } IPackage targetPackage = this.packageHandler.FetchPackage(args.PackageId, args.PackageVersion); if (targetPackage == null) { return false; } IEnumerable<IPackage> dependencyPackages = this.packageHandler.GetInstalledDependencies(targetPackage); // Check that there are analyzers in the target package from which information can be extracted // Create a mapping of packages to analyzers to avoid having to search for analyzers more than once Dictionary<IPackage, IEnumerable<DiagnosticAnalyzer>> analyzersByPackage = new Dictionary<IPackage, IEnumerable<DiagnosticAnalyzer>>(); IEnumerable<DiagnosticAnalyzer> targetAnalyzers = GetAnalyzers(targetPackage, args.Language); if (targetAnalyzers.Any()) { analyzersByPackage.Add(targetPackage, targetAnalyzers); } else { this.logger.LogWarning(UIResources.APG_NoAnalyzersFound, targetPackage.Id); if (!args.RecurseDependencies) { this.logger.LogWarning(UIResources.APG_NoAnalyzersInTargetSuggestRecurse); return false; } } if (args.RecurseDependencies) { // Possible sub-case - target package has dependencies that contain analyzers foreach (IPackage dependencyPackage in dependencyPackages) { IEnumerable<DiagnosticAnalyzer> dependencyAnalyzers = GetAnalyzers(dependencyPackage, args.Language); if (dependencyAnalyzers.Any()) { analyzersByPackage.Add(dependencyPackage, dependencyAnalyzers); } else { this.logger.LogWarning(UIResources.APG_NoAnalyzersFound, dependencyPackage.Id); } } if (!analyzersByPackage.Any()) { return false; } } // Check for packages that require the user to accept a license IEnumerable<IPackage> licenseAcceptancePackages = this.GetPackagesRequiringLicenseAcceptance(targetPackage); if (licenseAcceptancePackages.Any() && !args.AcceptLicenses) { // NB: This warns for all packages under the target that require license acceptance // (even if they aren't related to the packages from which plugins were generated) this.logger.LogError(UIResources.APG_NGPackageRequiresLicenseAcceptance, targetPackage.Id, targetPackage.Version.ToString()); this.ListPackagesRequiringLicenseAcceptance(licenseAcceptancePackages); return false; } List<string> generatedJarFiles = new List<string>(); // Initial run with the user-targeted package and arguments if (analyzersByPackage.ContainsKey(targetPackage)) { string generatedJarPath = GeneratePluginForPackage(args.OutputDirectory, args.Language, args.SqaleFilePath, targetPackage, analyzersByPackage[targetPackage]); if (generatedJarPath == null) { return false; } generatedJarFiles.Add(generatedJarPath); analyzersByPackage.Remove(targetPackage); } // Dependent package generation changes the arguments if (args.RecurseDependencies) { this.logger.LogWarning(UIResources.APG_RecurseEnabled_SQALENotEnabled); foreach (IPackage currentPackage in analyzersByPackage.Keys) { // No way to specify the SQALE file for any but the user-targeted package at this time string generatedJarPath = GeneratePluginForPackage(args.OutputDirectory, args.Language, null, currentPackage, analyzersByPackage[currentPackage]); if (generatedJarPath == null) { return false; } generatedJarFiles.Add(generatedJarPath); } } LogAcceptedPackageLicenses(licenseAcceptancePackages); foreach (string generatedJarFile in generatedJarFiles) { this.logger.LogInfo(UIResources.APG_PluginGenerated, generatedJarFile); } return true; }
public ProcessedArgs Process(string[] commandLineArgs) { ProcessedArgs processed = null; IEnumerable<ArgumentInstance> arguments; // This call will fail if there are duplicate, missing, or unrecognized arguments CommandLineParser parser = new CommandLineParser(Descriptors, false /* don't allow unrecognized */); bool parsedOk = parser.ParseArguments(commandLineArgs, this.logger, out arguments); NuGetReference analyzerRef; parsedOk &= TryParseAnalyzerRef(arguments, out analyzerRef); string sqaleFilePath; parsedOk &= TryParseSqaleFile(arguments, out sqaleFilePath); bool acceptLicense = GetLicenseAcceptance(arguments); if (parsedOk) { Debug.Assert(analyzerRef != null, "Expecting to have a valid analyzer reference"); processed = new ProcessedArgs( analyzerRef.PackageId, analyzerRef.Version, SupportedLanguages.CSharp, /* TODO: support multiple languages */ sqaleFilePath, acceptLicense, System.IO.Directory.GetCurrentDirectory()); } return processed; }
public bool Generate(ProcessedArgs args) { if (args == null) { throw new ArgumentNullException("args"); } IPackage package = this.packageHandler.FetchPackage(args.PackageId, args.PackageVersion); if (package == null) { return false; } string packageDir = this.packageHandler.GetLocalPackageRootDirectory(package); IEnumerable<DiagnosticAnalyzer> analyzers = GetAnalyzers(packageDir, this.packageHandler.LocalCacheRoot, args.Language); if (!analyzers.Any()) { return false; } IEnumerable<IPackage> licenseAcceptancePackages = this.GetPackagesRequiringLicenseAcceptance(package); if (licenseAcceptancePackages.Any() && ! args.AcceptLicenses) { this.logger.LogError(UIResources.APG_NGPackageRequiresLicenseAcceptance, package.Id, package.Version.ToString()); this.ListPackagesRequiringLicenseAcceptance(licenseAcceptancePackages); return false; } string createdJarFilePath = null; string baseDirectory = CreateBaseWorkingDirectory(); // Collect the remaining data required to build the plugin RoslynPluginDefinition definition = new RoslynPluginDefinition(); definition.Language = args.Language; definition.SqaleFilePath = args.SqaleFilePath; definition.PackageId = package.Id; definition.PackageVersion = package.Version.ToString(); definition.Manifest = CreatePluginManifest(package); // Create a zip containing the required analyzer files definition.SourceZipFilePath = this.CreateAnalyzerStaticPayloadFile(packageDir, baseDirectory); definition.StaticResourceName = Path.GetFileName(definition.SourceZipFilePath); definition.RulesFilePath = GenerateRulesFile(analyzers, baseDirectory); string generatedSqaleFile = null; bool generate = true; if (definition.SqaleFilePath == null) { generatedSqaleFile = CalculateSqaleFileName(package, args.OutputDirectory); GenerateFixedSqaleFile(analyzers, generatedSqaleFile); Debug.Assert(File.Exists(generatedSqaleFile)); } else { generate = IsValidSqaleFile(definition.SqaleFilePath); } if (generate) { createdJarFilePath = BuildPlugin(definition, args.OutputDirectory); } LogSummary(createdJarFilePath, generatedSqaleFile, licenseAcceptancePackages); return createdJarFilePath != null; }
private static void AssertArgumentsProcessed(ProcessedArgs actualArgs, TestLogger logger, string expectedId, string expectedVersion, string expectedSqale) { Assert.IsNotNull(actualArgs, "Expecting the arguments to have been processed successfully"); Assert.IsNotNull(actualArgs.AnalyzerRef, "Not expecting the analyzer reference to be null"); Assert.AreEqual(actualArgs.AnalyzerRef.PackageId, expectedId, "Unexpected package id returned"); NuGetReference actualRef = actualArgs.AnalyzerRef; if (expectedVersion == null) { Assert.IsNull(actualRef.Version, "Expecting the version to be null"); } else { Assert.IsNotNull(actualRef.Version, "Not expecting the version to be null"); Assert.AreEqual(expectedVersion, actualRef.Version.ToString()); } Assert.AreEqual(expectedSqale, actualArgs.SqaleFilePath, "Unexpected sqale file path"); if (expectedSqale != null) { Assert.IsTrue(File.Exists(expectedSqale), "Specified sqale file should exist: {0}", expectedSqale); } logger.AssertErrorsLogged(0); }