public void ExtractSnippet_FileDoesNotExist_ReturnEmpty() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false); var regionCache = new FileRegionsCache(fileSystem: mock.Object); LocationModel location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("file://temp.cs") }, Region = new Region { Snippet = new ArtifactContent { Text = "private class Class5" } }, }, }.ToLocationModel(new Run(), 1, 1); string snippet = location.ExtractSnippet(regionCache, mock.Object); snippet.Should().BeEquivalentTo(string.Empty); }
public void ToReplacementModel_RelativeUri_BinaryReplacement() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false); mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample); var regionCache = new FileRegionsCache(fileSystem: mock.Object); Uri uri = new Uri(RelativeFilePath, UriKind.Relative); byte[] bytes = Encoding.UTF8.GetBytes(ReplacementText); Replacement replacement = new Replacement { DeletedRegion = new Region { ByteOffset = 210, }, InsertedContent = new ArtifactContent { Binary = Convert.ToBase64String(bytes), }, }; ReplacementModel model = replacement.ToReplacementModel(regionCache, uri); model.Should().NotBeNull(); model.InsertedString.Should().BeNull(); model.InsertedBytes.Should().BeEquivalentTo(bytes); model.Region.Should().NotBeNull(); model.Region.IsBinaryRegion.Should().BeTrue(); model.Region.CharOffset.Should().Be(-1); model.Region.ByteOffset.Should().Be(210); }
public void ExtractSnippet_FileExists_ReturnEmpty() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(true); mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample); var regionCache = new FileRegionsCache(fileSystem: mock.Object); string expectedSnippet = "internal class Class4"; LocationModel location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("file://temp.cs") }, Region = new Region { Snippet = new ArtifactContent { Text = expectedSnippet }, StartLine = 7, StartColumn = 5, EndLine = 7, EndColumn = 25, }, }, }.ToLocationModel(new Run(), 1, 1); string snippet = location.ExtractSnippet(regionCache, mock.Object); snippet.Should().BeEquivalentTo(expectedSnippet); }
public void ToFixModel_FileDoesNotExists_FixIsNotApplyable() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false); mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(string.Empty); var regionCache = new FileRegionsCache(fileSystem: mock.Object); string descriptionString = "test description"; string replacementText = "public class"; var fix = new Fix { Description = new Message { Text = descriptionString }, ArtifactChanges = new List <ArtifactChange> { new ArtifactChange { ArtifactLocation = new ArtifactLocation { Uri = new Uri(AnotherFilePath, UriKind.Absolute), }, Replacements = new List <Replacement> { new Replacement { DeletedRegion = new Region { CharOffset = 196, CharLength = 14, }, InsertedContent = new ArtifactContent { Text = replacementText }, }, }, }, }, }.ToFixModel(originalUriBaseIds: null, regionCache); fix.Description.Should().BeEquivalentTo(descriptionString); fix.ArtifactChanges.Count.Should().Be(1); fix.CanBeAppliedToFile(FilePath).Should().BeFalse(); ObservableCollection <ReplacementModel> replacements = fix.ArtifactChanges.FirstOrDefault().Replacements; // file doesn't exist, output replacement should have be same as input region. replacements.Count.Should().Be(1); ReplacementModel replacement = replacements.FirstOrDefault(); replacement.InsertedString.Should().BeEquivalentTo(replacementText); replacement.Region.CharOffset.Should().Be(196); replacement.Region.CharLength.Should().Be(14); replacement.Region.StartLine.Should().Be(0); replacement.Region.EndLine.Should().Be(0); replacement.Region.StartColumn.Should().Be(0); replacement.Region.EndColumn.Should().Be(0); }
public void ToReplacementModel_RelativeUri_TextReplacement() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false); mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample); var regionCache = new FileRegionsCache(fileSystem: mock.Object); Uri uri = new Uri(RelativeFilePath, UriKind.Relative); Replacement replacement = new Replacement { DeletedRegion = new Region { CharOffset = 196, CharLength = 14, }, InsertedContent = new ArtifactContent { Text = ReplacementText, }, }; ReplacementModel model = replacement.ToReplacementModel(regionCache, uri); model.Should().NotBeNull(); model.InsertedBytes.Should().BeNull(); model.InsertedString.Should().BeEquivalentTo(ReplacementText); model.Region.Should().NotBeNull(); model.Region.CharLength.Should().Be(14); model.Region.CharOffset.Should().Be(196); model.Region.IsBinaryRegion.Should().BeFalse(); model.Region.ByteOffset.Should().Be(-1); }
public void FileRegionsCache_ProperlyCaches() { Uri uri = new Uri(@"C:\Code\Program.cs"); StringBuilder fileContents = new StringBuilder(); for (int i = 0; i < 1000; ++i) { fileContents.AppendLine("0123456789"); } Run run = new Run(); IFileSystem mockFileSystem = MockFactory.MakeMockFileSystem(uri.LocalPath, fileContents.ToString()); FileRegionsCache fileRegionsCache = new FileRegionsCache(run, fileSystem: mockFileSystem); Region region = new Region() { StartLine = 2, StartColumn = 1, EndLine = 3, EndColumn = 10, }; Stopwatch w = Stopwatch.StartNew(); for (int i = 0; i < 1000; ++i) { Region copy = region.DeepClone(); Region populated = fileRegionsCache.PopulateTextRegionProperties(copy, uri, populateSnippet: true); } // Runtime should be way under 100ms if caching, and much longer otherwise w.Stop(); Assert.True(w.ElapsedMilliseconds < 100); }
public void ToFixModel_FileExists_FixIsApplyable() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(true); mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample); var regionCache = new FileRegionsCache(fileSystem: mock.Object); string descriptionString = "test description"; string replacementText = "public class"; var fix = new Fix { Description = new Message { Text = descriptionString }, ArtifactChanges = new List <ArtifactChange> { new ArtifactChange { ArtifactLocation = new ArtifactLocation { Uri = new Uri(FilePath, UriKind.Absolute), }, Replacements = new List <Replacement> { new Replacement { DeletedRegion = new Region { CharOffset = 196, CharLength = 14, }, InsertedContent = new ArtifactContent { Text = replacementText }, }, }, }, }, }.ToFixModel(originalUriBaseIds: null, regionCache); fix.Description.Should().BeEquivalentTo(descriptionString); fix.ArtifactChanges.Count.Should().Be(1); fix.CanBeAppliedToFile(FilePath).Should().BeTrue(); ObservableCollection <ReplacementModel> replacements = fix.ArtifactChanges.FirstOrDefault().Replacements; // input replacement is charoffset based. output replacement should have start/end line/column info. replacements.Count.Should().Be(1); ReplacementModel replacement = replacements.FirstOrDefault(); replacement.InsertedString.Should().BeEquivalentTo(replacementText); replacement.Region.StartLine.Should().Be(6); replacement.Region.EndLine.Should().Be(6); replacement.Region.StartColumn.Should().Be(7); replacement.Region.EndColumn.Should().Be(21); }
public override PhysicalLocation VisitPhysicalLocation(PhysicalLocation node) { if (node.Region == null || node.Region.IsBinaryRegion) { goto Exit; } bool insertRegionSnippets = _dataToInsert.HasFlag(OptionallyEmittedData.RegionSnippets); bool overwriteExistingData = _dataToInsert.HasFlag(OptionallyEmittedData.OverwriteExistingData); bool insertContextCodeSnippets = _dataToInsert.HasFlag(OptionallyEmittedData.ContextRegionSnippets); bool populateRegionProperties = _dataToInsert.HasFlag(OptionallyEmittedData.ComprehensiveRegionProperties); if (insertRegionSnippets || populateRegionProperties || insertContextCodeSnippets) { Region expandedRegion; _fileRegionsCache = _fileRegionsCache ?? new FileRegionsCache(_run); // If we can resolve a file location to a newly constructed // absolute URI, we will prefer that if (!node.ArtifactLocation.TryReconstructAbsoluteUri(_run.OriginalUriBaseIds, out Uri resolvedUri)) { resolvedUri = node.ArtifactLocation.Uri; } if (!resolvedUri.IsAbsoluteUri) { goto Exit; } expandedRegion = _fileRegionsCache.PopulateTextRegionProperties(node.Region, resolvedUri, populateSnippet: insertRegionSnippets); ArtifactContent originalSnippet = node.Region.Snippet; if (populateRegionProperties) { node.Region = expandedRegion; } if (originalSnippet == null || overwriteExistingData) { node.Region.Snippet = expandedRegion.Snippet; } else { node.Region.Snippet = originalSnippet; } if (insertContextCodeSnippets && (node.ContextRegion == null || overwriteExistingData)) { node.ContextRegion = _fileRegionsCache.ConstructMultilineContextSnippet(expandedRegion, resolvedUri); } } Exit: return(base.VisitPhysicalLocation(node)); }
private static void ExecuteTests(string fileText, ReadOnlyCollection <TestCaseData> testCases) { Uri uri = new Uri(@"c:\temp\myFile.cpp"); var run = new Run(); IFileSystem mockFileSystem = MockFactory.MakeMockFileSystem(uri.LocalPath, fileText); var fileRegionsCache = new FileRegionsCache(run, fileSystem: mockFileSystem); ExecuteTests(testCases, fileRegionsCache, uri); }
// This method is called when you click an inline link, with an integer target, which // points to a Location object that has a region associated with it. internal IVsWindowFrame NavigateTo(bool usePreviewPane) { ThreadHelper.ThrowIfNotOnUIThread(); // Before anything else, see if this is an external link we should open in the browser. Uri uri; if (Uri.TryCreate(this.FullFilePath, UriKind.Absolute, out uri)) { if (!uri.IsFile) { System.Diagnostics.Process.Start(uri.OriginalString); return(null); } } // Fall back to the file and line number if (!File.Exists(this.FullFilePath)) { if (!CodeAnalysisResultManager.Instance.TryRebaselineAllSarifErrors(_runId, this.UriBaseId, this.FullFilePath)) { return(null); } } if (File.Exists(this.FullFilePath) && Uri.TryCreate(this.FullFilePath, UriKind.Absolute, out uri)) { // Fill out the region's properties FileRegionsCache regionsCache = CodeAnalysisResultManager.Instance.RunDataCaches[_runId].FileRegionsCache; Region = regionsCache.PopulateTextRegionProperties(Region, uri, true); } IVsWindowFrame windowFrame = SdkUIUtilities.OpenDocument(SarifViewerPackage.ServiceProvider, this.FullFilePath, usePreviewPane); if (windowFrame != null) { IVsTextView textView = GetTextViewFromFrame(windowFrame); if (textView == null) { return(null); } var sourceLocation = this.GetSourceLocation(); // Navigate the caret to the desired location. Text span uses 0-based indexes TextSpan ts; ts.iStartLine = sourceLocation.StartLine - 1; ts.iEndLine = sourceLocation.EndLine - 1; ts.iStartIndex = Math.Max(sourceLocation.StartColumn - 1, 0); ts.iEndIndex = Math.Max(sourceLocation.EndColumn - 1, 0); textView.EnsureSpanVisible(ts); textView.SetSelection(ts.iStartLine, ts.iStartIndex, ts.iEndLine, ts.iEndIndex); } return(windowFrame); }
public SearchSkimmer(IRegex engine, ValidatorsCache validators, FileRegionsCache fileRegionsCache, SearchDefinition definition, IFileSystem fileSystem = null) : this( engine, validators, fileRegionsCache, definition.Id, definition.Name, definition.Description, definition.MatchExpressions, fileSystem) { }
public static string ExtractSnippet(this LocationModel location, FileRegionsCache fileRegionsCache, IFileSystem fileSystem = null) { fileSystem ??= FileSystem.Instance; if (fileSystem.FileExists(location.FilePath) && Uri.TryCreate(location.FilePath, UriKind.Absolute, out Uri uri)) { // Fill out the region's properties fileRegionsCache ??= new FileRegionsCache(); Region fullyPopulatedRegion = fileRegionsCache.PopulateTextRegionProperties(location.Region, uri, populateSnippet: true); return(fullyPopulatedRegion?.Snippet != null ? fullyPopulatedRegion.Snippet.Text : string.Empty); } return(string.Empty); }
public void ToReplacementModel_NullReplacement_ReturnNull() { var mock = new Mock <IFileSystem>(); mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false); mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample); var regionCache = new FileRegionsCache(fileSystem: mock.Object); Uri uri = new Uri(FilePath); Replacement replacement = null; ReplacementModel model = replacement.ToReplacementModel(regionCache, uri); model.Should().BeNull(); }
public void FileRegionsCache_PopulatesNullRegion() { Uri uri = new Uri(@"c:\temp\myFile.cpp"); var run = new Run(); IFileSystem mockFileSystem = MockFactory.MakeMockFileSystem(uri.LocalPath, SPEC_EXAMPLE); var fileRegionsCache = new FileRegionsCache(run, fileSystem: mockFileSystem); Region region = fileRegionsCache.PopulateTextRegionProperties(inputRegion: null, uri: uri, populateSnippet: false); region.Should().BeNull(); region = fileRegionsCache.PopulateTextRegionProperties(inputRegion: null, uri: uri, populateSnippet: true); region.Should().BeNull(); }
public void FileRegionsCache_PopulatesFromMissingFile() { var run = new Run(); var fileRegionsCache = new FileRegionsCache(run); Uri uri = new Uri(@"c:\temp\DoesNotExist\" + Guid.NewGuid().ToString() + ".cpp"); Region region = new Region() { CharOffset = 17 }; // Region should not be touched in any way if the file it references is missing fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: false).ValueEquals(region).Should().BeTrue(); fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: true).ValueEquals(region).Should().BeTrue(); }
public SearchSkimmer( IRegex engine, ValidatorsCache validators, FileRegionsCache fileRegionsCache, string id, string name, string description, IList <MatchExpression> matchExpressions, IFileSystem fileSystem = null) { _id = id; _name = name; _engine = engine; _validators = validators; _fileRegionsCache = fileRegionsCache; _fullDescription = new MultiformatMessageString { Text = description }; _fileSystem = fileSystem ?? FileSystem.Instance; _messageStrings = new Dictionary <string, MultiformatMessageString> { { nameof(SdkResources.NotApplicable_InvalidMetadata), new MultiformatMessageString() { Text = SdkResources.NotApplicable_InvalidMetadata, } }, }; foreach (MatchExpression matchExpression in matchExpressions) { string matchExpressionMessage = matchExpression.Message; matchExpression.ArgumentNameToIndexMap = GenerateIndicesForNamedArguments(ref matchExpressionMessage); string messageId = matchExpression.SubId ?? "Default"; if (!_messageStrings.TryGetValue(messageId, out MultiformatMessageString mfString)) { _messageStrings[messageId] = new MultiformatMessageString { Text = matchExpressionMessage, }; } } _matchExpressions = matchExpressions; }
public void FileRegionsCache_ValidateConcurrencyData() { Exception exception = Record.Exception(() => { var fileRegionsCache = new FileRegionsCache(); List <Task> taskList = new List <Task>(); for (int i = 0; i < 1_000; i++) { taskList.Add(Task.Factory.StartNew(() => fileRegionsCache.PopulateTextRegionProperties(new Region { }, new Uri($"file:///c:/{Guid.NewGuid()}.txt"), true))); } Task.WaitAll(taskList.ToArray()); }); Assert.Null(exception); }
public static string ExtractSnippet(this Location location, Run run, FileRegionsCache fileRegionsCache) { PhysicalLocation physicalLocation = location.PhysicalLocation; ArtifactLocation artifactLocation = location.PhysicalLocation?.ArtifactLocation; Region region = location.PhysicalLocation?.Region; Uri uri = location.PhysicalLocation?.ArtifactLocation?.Uri; if (uri == null || region == null || region.IsBinaryRegion || physicalLocation == null) { return(string.Empty); } if (region.Snippet != null) { return(region.Snippet.Text); } if (artifactLocation.Uri == null && artifactLocation.Index >= 0) { // Uri is not stored at result level, but we have an index to go look in run.Artifacts // we must pick the ArtifactLocation details from run.artifacts array Artifact artifactFromRun = run.Artifacts[artifactLocation.Index]; artifactLocation = artifactFromRun.Location; } // If we can resolve a file location to a newly constructed // absolute URI, we will prefer that if (!artifactLocation.TryReconstructAbsoluteUri(run.OriginalUriBaseIds, out Uri resolvedUri)) { resolvedUri = artifactLocation.Uri; } if (!resolvedUri.IsAbsoluteUri) { return(string.Empty); } fileRegionsCache ??= new FileRegionsCache(); Region expandedRegion = fileRegionsCache.PopulateTextRegionProperties(region, resolvedUri, populateSnippet: true); return(expandedRegion.Snippet != null ? expandedRegion.Snippet.Text : string.Empty); }
private SearchSkimmer CreateSkimmer( SearchDefinition definition, IRegex engine = null, ValidatorsCache validators = null, FileRegionsCache fileRegionsCache = null, IFileSystem fileSystem = null) { var definitions = new SearchDefinitions { Definitions = new List <SearchDefinition>(new[] { definition }), }; definitions = AnalyzeCommand.PushInheritedData(definitions, sharedStrings: null); return(new SearchSkimmer( engine: engine ?? RE2Regex.Instance, validators: validators, fileRegionsCache: fileRegionsCache ?? new FileRegionsCache(), definition: definitions.Definitions[0], fileSystem: fileSystem)); }
public void FileRegionsCache_PopulatesUsingProvidedText() { var run = new Run(); var fileRegionsCache = new FileRegionsCache(); Uri uri = new Uri(@"c:\temp\DoesNotExist\" + Guid.NewGuid().ToString() + ".cpp"); string fileText = "12345\n56790\n"; int charOffset = 6; int charLength = 1; // Region should grab the second line of text in 'fileText'. Region region = new Region() { CharOffset = charOffset, CharLength = charLength }; Region expected = new Region() { CharOffset = charOffset, CharLength = charLength, StartLine = 2, EndLine = 2, StartColumn = 1, EndColumn = 2 }; Region actual; // Region should not be touched in any way if the file it references is missing actual = fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: false, fileText: fileText); actual.ValueEquals(expected).Should().BeTrue(); actual.Snippet.Should().BeNull(); actual = fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: true, fileText: fileText); actual.Snippet.Text.Should().Be(fileText.Substring(charOffset, charLength)); actual.Snippet = null; actual.ValueEquals(expected).Should().BeTrue(); }
public void ToReplacementModel_WhenUriIsRelativeAndReplacementRegionIsCharOffsetLength_ProducesExpectedModel() { const string FilePath = "test.txt"; var fileUri = new Uri(FilePath, UriKind.Relative); const int DeletedCharOffset = 12; const int DeletedCharLength = 2; const string ReplacementString = "FortyTwo"; var replacement = new Replacement { InsertedContent = new ArtifactContent { Text = ReplacementString, }, DeletedRegion = new Region { CharOffset = DeletedCharOffset, CharLength = DeletedCharLength, }, }; var run = new Run(); var mockFileSystem = new Mock <IFileSystem>(); var fileRegionsCache = new FileRegionsCache(FileRegionsCacheCapacity, mockFileSystem.Object); var actualModel = replacement.ToReplacementModel(fileRegionsCache, fileUri); actualModel.Region.CharOffset.Should().Be(DeletedCharOffset); actualModel.Region.CharLength.Should().Be(DeletedCharLength); actualModel.IsTextReplacement.Should().BeTrue(); actualModel.IsBinaryReplacement.Should().BeFalse(); actualModel.InsertedString.Should().Be(ReplacementString); // The run does not contain any path information, so when the FileRegionsCache is // constructed, it does not consult the file system. mockFileSystem.VerifyNoOtherCalls(); }
internal void RemapFilePath(string originalPath, string remappedPath) { ThreadHelper.ThrowIfNotOnUIThread(); DetachFromDocument(_documentCookie); var uri = new Uri(remappedPath, UriKind.Absolute); FileRegionsCache regionsCache = CodeAnalysisResultManager.Instance.RunDataCaches[_runId].FileRegionsCache; if (FileName.Equals(originalPath, StringComparison.OrdinalIgnoreCase)) { FileName = remappedPath; } foreach (LocationModel location in Locations) { if (location.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase)) { location.FilePath = remappedPath; location.Region = regionsCache.PopulateTextRegionProperties(location.Region, uri, true); } } foreach (LocationModel location in RelatedLocations) { if (location.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase)) { location.FilePath = remappedPath; location.Region = regionsCache.PopulateTextRegionProperties(location.Region, uri, true); } } foreach (CallTree callTree in CallTrees) { Stack <CallTreeNode> nodesToProcess = new Stack <CallTreeNode>(); foreach (CallTreeNode topLevelNode in callTree.TopLevelNodes) { nodesToProcess.Push(topLevelNode); } while (nodesToProcess.Count > 0) { CallTreeNode current = nodesToProcess.Pop(); try { if (current.FilePath != null && current.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase)) { current.FilePath = remappedPath; current.Region = regionsCache.PopulateTextRegionProperties(current.Region, uri, true); } } catch (ArgumentException) { // An argument exception is thrown if the node does not have a region. // Since there's no region, there's no document to attach to. // Just move on with processing the child nodes. } foreach (CallTreeNode childNode in current.Children) { nodesToProcess.Push(childNode); } } } foreach (StackCollection stackCollection in Stacks) { foreach (StackFrameModel stackFrame in stackCollection) { if (stackFrame.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase)) { stackFrame.FilePath = remappedPath; stackFrame.Region = regionsCache.PopulateTextRegionProperties(stackFrame.Region, uri, true); } } } foreach (FixModel fixModel in Fixes) { foreach (ArtifactChangeModel fileChangeModel in fixModel.ArtifactChanges) { if (fileChangeModel.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase)) { fileChangeModel.FilePath = remappedPath; } } } AttachToDocument(); }
private static void ExecuteTests(ReadOnlyCollection <TestCaseData> testCases, FileRegionsCache fileRegionsCache, Uri uri) { foreach (TestCaseData testCase in testCases) { Region inputRegion = testCase.InputRegion; Region expectedRegion = testCase.OutputRegion.DeepClone(); ArtifactContent snippet = expectedRegion.Snippet; expectedRegion.Snippet = null; Region actualRegion = fileRegionsCache.PopulateTextRegionProperties(inputRegion, uri, populateSnippet: false); actualRegion.ValueEquals(expectedRegion).Should().BeTrue(); actualRegion.Snippet.Should().BeNull(); expectedRegion.Snippet = snippet; actualRegion = fileRegionsCache.PopulateTextRegionProperties(inputRegion, uri, populateSnippet: true); actualRegion.ValueEquals(expectedRegion).Should().BeTrue(); if (snippet == null) { actualRegion.Snippet.Should().BeNull(); } else { actualRegion.Snippet.Text.Should().Be(snippet.Text); } } }
public static ArtifactChangeModel ToArtifactChangeModel(this ArtifactChange fileChange, IDictionary <string, Uri> originalUriBaseIds, FileRegionsCache fileRegionsCache) { if (fileChange == null) { return(null); } Dictionary <string, ArtifactLocation> uriToArtifactLocationMap = null; if (originalUriBaseIds != null) { // convert IDictionary<string, Uri> to IDictionary<string, ArtifactLocation> which // is needed by Sarif.SDK extension method ArtifactLocation.TryReconstructAbsoluteUri() uriToArtifactLocationMap = new Dictionary <string, ArtifactLocation>(originalUriBaseIds.Count); foreach (KeyValuePair <string, Uri> entry in originalUriBaseIds) { uriToArtifactLocationMap.Add(entry.Key, new ArtifactLocation { Uri = entry.Value }); } } return(fileChange.ToArtifactChangeModel(uriToArtifactLocationMap, fileRegionsCache)); }
public static FixModel ToFixModel(this Fix fix, IDictionary <string, ArtifactLocation> originalUriBaseIds, FileRegionsCache fileRegionsCache) { fix = fix ?? throw new ArgumentNullException(nameof(fix)); var model = new FixModel(fix.Description?.Text); if (fix.ArtifactChanges != null) { foreach (ArtifactChange change in fix.ArtifactChanges) { model.ArtifactChanges.Add(change.ToArtifactChangeModel(originalUriBaseIds, fileRegionsCache)); } } return(model); }
public void ExtractSnippet_ReturnsExpectedValue() { var mock = new Mock <IFileSystem>(); var regionCache = new FileRegionsCache(fileSystem: mock.Object); var testCases = new[] { new { location = new Location { PhysicalLocation = null }, run = new Run(), regionCache = regionCache, expectedResult = string.Empty, }, new { location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = null } }, run = new Run(), regionCache = regionCache, expectedResult = string.Empty, }, new { location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = null } } }, run = new Run(), regionCache = regionCache, expectedResult = string.Empty, }, new { location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("file://temp.cs") } } }, run = new Run(), regionCache = regionCache, expectedResult = string.Empty, }, new { location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("file://temp.cs") }, Region = new Region(), }, }, run = new Run(), regionCache = regionCache, expectedResult = string.Empty, }, new { location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("file://temp.cs") }, Region = new Region { ByteOffset = 0 }, }, }, run = new Run(), regionCache = regionCache, expectedResult = string.Empty, }, new { location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("file://temp.cs") }, Region = new Region { Snippet = new ArtifactContent { Text = "private class Class5" } }, }, }, run = new Run(), regionCache = regionCache, expectedResult = "private class Class5", }, }; int failedCases = 0; foreach (var testcase in testCases) { string snippet = testcase.location.ExtractSnippet(testcase.run, testcase.regionCache); if (snippet != testcase.expectedResult) { failedCases++; } } failedCases.Should().Be(0, "failed test cases: " + failedCases.ToString()); }
public static ISet <Skimmer <AnalyzeContext> > CreateSkimmersFromDefinitionsFiles( IFileSystem fileSystem, IEnumerable <string> searchDefinitionsPaths, IRegex engine = null) { engine ??= RE2Regex.Instance; var validators = new ValidatorsCache(); FileRegionsCache fileRegionsCache = FileRegionsCache.Instance; var skimmers = new HashSet <Skimmer <AnalyzeContext> >(); // TODO exception handling for bad search definitions files foreach (string searchDefinitionsPath in searchDefinitionsPaths) { string searchDefinitionsText = fileSystem.FileReadAllText(searchDefinitionsPath); SearchDefinitions definitions = JsonConvert.DeserializeObject <SearchDefinitions>(searchDefinitionsText); // This would skip files that does not look like rules. if (definitions == null || definitions.Definitions == null) { continue; } string validatorPath = null; string definitionsDirectory = Path.GetDirectoryName(searchDefinitionsPath); if (!string.IsNullOrEmpty(definitions.ValidatorsAssemblyName)) { // TODO File.Exists check? Logging if not locatable? validatorPath = Path.Combine(definitionsDirectory, definitions.ValidatorsAssemblyName); validators.ValidatorPaths.Add(validatorPath); } else { // If no explicit name of a validator binary was provided, // we look for one that lives alongside the definitions file. validatorPath = Path.GetFileNameWithoutExtension(searchDefinitionsPath) + ".dll"; validatorPath = Path.Combine(definitionsDirectory, validatorPath); if (File.Exists(validatorPath)) { validators.ValidatorPaths.Add(validatorPath); } } Dictionary <string, string> sharedStrings = null; if (!string.IsNullOrEmpty(definitions.SharedStringsFileName)) { string sharedStringsFullPath = Path.Combine(definitionsDirectory, definitions.SharedStringsFileName); sharedStrings = LoadSharedStrings(sharedStringsFullPath, fileSystem); } definitions = PushInheritedData(definitions, sharedStrings); foreach (SearchDefinition definition in definitions.Definitions) { Skimmer <AnalyzeContext> skimmer = skimmers.FirstOrDefault(skimmer => skimmer.Id == definition.Id); if (skimmer != null) { skimmers.Remove(skimmer); } skimmers.Add( new SearchSkimmer( engine: engine, validators: validators, fileRegionsCache: fileRegionsCache, definition)); const string singleSpace = " "; // Send no-op match operations through engine in order to drive caching of all regexes. if (definition.FileNameAllowRegex != null) { engine.Match(singleSpace, definition.FileNameAllowRegex, RegexDefaults.DefaultOptionsCaseSensitive); } foreach (MatchExpression matchExpression in definition.MatchExpressions) { if (!string.IsNullOrEmpty(matchExpression.FileNameAllowRegex)) { engine.Match(singleSpace, matchExpression.FileNameAllowRegex, RegexDefaults.DefaultOptionsCaseSensitive); } if (!string.IsNullOrEmpty(matchExpression.ContentsRegex)) { engine.Match(singleSpace, matchExpression.ContentsRegex, RegexDefaults.DefaultOptionsCaseSensitive); } } } } return(skimmers); }
public static ReplacementModel ToReplacementModel(this Replacement replacement, FileRegionsCache fileRegionsCache, Uri uri) { if (replacement == null) { return(null); } var model = new ReplacementModel { Region = uri.IsAbsoluteUri ? fileRegionsCache.PopulateTextRegionProperties(replacement.DeletedRegion, uri, populateSnippet: false) : replacement.DeletedRegion, }; if (model.Region.CharOffset >= 0) { // This is a text replacement. model.InsertedString = replacement.InsertedContent?.Text; } else { // This is a binary replacement, but don't try to convert the replacement // content to a string if there isn't any. if (replacement.InsertedContent?.Binary != null) { model.InsertedBytes = Convert.FromBase64String(replacement.InsertedContent.Binary); } } return(model); }
public override PhysicalLocation VisitPhysicalLocation(PhysicalLocation node) { if (node.Region == null || node.Region.IsBinaryRegion) { goto Exit; } bool insertRegionSnippets = _dataToInsert.HasFlag(OptionallyEmittedData.RegionSnippets); bool overwriteExistingData = _dataToInsert.HasFlag(OptionallyEmittedData.OverwriteExistingData); bool insertContextCodeSnippets = _dataToInsert.HasFlag(OptionallyEmittedData.ContextRegionSnippets); bool populateRegionProperties = _dataToInsert.HasFlag(OptionallyEmittedData.ComprehensiveRegionProperties); if (insertRegionSnippets || populateRegionProperties || insertContextCodeSnippets) { Region expandedRegion; ArtifactLocation artifactLocation = node.ArtifactLocation; _fileRegionsCache = _fileRegionsCache ?? new FileRegionsCache(_run); if (artifactLocation.Uri == null && artifactLocation.Index >= 0) { // Uri is not stored at result level, but we have an index to go look in run.Artifacts // we must pick the ArtifactLocation details from run.artifacts array Artifact artifactFromRun = _run.Artifacts[artifactLocation.Index]; artifactLocation = artifactFromRun.Location; } // If we can resolve a file location to a newly constructed // absolute URI, we will prefer that if (!artifactLocation.TryReconstructAbsoluteUri(_run.OriginalUriBaseIds, out Uri resolvedUri)) { resolvedUri = artifactLocation.Uri; } if (!resolvedUri.IsAbsoluteUri) { goto Exit; } expandedRegion = _fileRegionsCache.PopulateTextRegionProperties(node.Region, resolvedUri, populateSnippet: insertRegionSnippets); ArtifactContent originalSnippet = node.Region.Snippet; if (populateRegionProperties) { node.Region = expandedRegion; } if (originalSnippet == null || overwriteExistingData) { node.Region.Snippet = expandedRegion.Snippet; } else { node.Region.Snippet = originalSnippet; } if (insertContextCodeSnippets && (node.ContextRegion == null || overwriteExistingData)) { node.ContextRegion = _fileRegionsCache.ConstructMultilineContextSnippet(expandedRegion, resolvedUri); } } Exit: return(base.VisitPhysicalLocation(node)); }
public RunDataCache(Run run) { FileRegionsCache = new FileRegionsCache(run); }