Skip to content

Commit 282a0aa

Browse files
Copilotbcollamore
andcommitted
fix: Address review feedback for LicenseAnalyzer - define constant for project.assets.json, simplify loop with LINQ, fix empty catch blocks, reduce cognitive complexity
Co-authored-by: bcollamore <57269455+bcollamore@users.noreply.github.com>
1 parent c41236d commit 282a0aa

2 files changed

Lines changed: 73 additions & 47 deletions

File tree

Philips.CodeAnalysis.SecurityAnalyzers/LicenseAnalyzer.cs

Lines changed: 72 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class LicenseAnalyzer : DiagnosticAnalyzer
2525

2626
public const string AllowedLicensesFileName = @"Allowed.Licenses.txt";
2727
public const string LicensesCacheFileName = @"licenses.json";
28+
private const string ProjectAssetsFileName = @"project.assets.json";
2829

2930
// Default acceptable licenses (permissive licenses that are generally safe to use)
3031
private static readonly HashSet<string> DefaultAcceptableLicenses = new(StringComparer.OrdinalIgnoreCase)
@@ -185,17 +186,15 @@ private static string TryFindAssetsFileFromSourcePaths()
185186
// Look for project.assets.json in common locations
186187
var possiblePaths = new[]
187188
{
188-
Path.Combine(currentDir, "obj", "project.assets.json"),
189-
Path.Combine(currentDir, "..", "obj", "project.assets.json"),
190-
Path.Combine(currentDir, "..", "..", "obj", "project.assets.json")
189+
Path.Combine(currentDir, "obj", ProjectAssetsFileName),
190+
Path.Combine(currentDir, "..", "obj", ProjectAssetsFileName),
191+
Path.Combine(currentDir, "..", "..", "obj", ProjectAssetsFileName)
191192
};
192193

193-
foreach (var path in possiblePaths)
194+
var foundPath = possiblePaths.Where(File.Exists).FirstOrDefault();
195+
if (foundPath != null)
194196
{
195-
if (File.Exists(path))
196-
{
197-
return path;
198-
}
197+
return foundPath;
199198
}
200199

201200
// If not found in common locations, search in current directory tree
@@ -204,7 +203,7 @@ private static string TryFindAssetsFileFromSourcePaths()
204203
var searchDir = currentDir;
205204
for (var i = 0; i < 5; i++) // Limit search depth
206205
{
207-
var assetsPath = Path.Combine(searchDir, "obj", "project.assets.json");
206+
var assetsPath = Path.Combine(searchDir, "obj", ProjectAssetsFileName);
208207
if (File.Exists(assetsPath))
209208
{
210209
return assetsPath;
@@ -269,6 +268,7 @@ private static void SaveLicenseCache(Dictionary<string, PackageLicenseInfo> cach
269268
catch (Exception)
270269
{
271270
// If we can't write cache, just continue without caching
271+
return;
272272
}
273273
}
274274

@@ -348,54 +348,79 @@ private static string ExtractLicenseFromNuspec(string nuspecPath)
348348
{
349349
var content = File.ReadAllText(nuspecPath);
350350

351-
// Simple XML parsing to extract license information
352-
// Look for <license> or <licenseUrl> elements
353-
var licenseStart = content.IndexOf("<license", StringComparison.OrdinalIgnoreCase);
354-
if (licenseStart >= 0)
351+
// Try to extract license from <license> element first
352+
var licenseFromElement = ExtractLicenseElement(content);
353+
if (!string.IsNullOrEmpty(licenseFromElement))
355354
{
356-
var typeStart = content.IndexOf("type=\"", licenseStart, StringComparison.OrdinalIgnoreCase);
357-
if (typeStart >= 0)
358-
{
359-
typeStart += 6; // Skip 'type="'
360-
var typeEnd = content.IndexOf("\"", typeStart, StringComparison.OrdinalIgnoreCase);
361-
if (typeEnd > typeStart)
362-
{
363-
var licenseType = content.Substring(typeStart, typeEnd - typeStart);
364-
if (licenseType.Equals("expression", StringComparison.OrdinalIgnoreCase))
365-
{
366-
// Extract SPDX expression
367-
var contentStart = content.IndexOf(">", licenseStart) + 1;
368-
var contentEnd = content.IndexOf("</license>", contentStart, StringComparison.OrdinalIgnoreCase);
369-
if (contentEnd > contentStart)
370-
{
371-
return content.Substring(contentStart, contentEnd - contentStart).Trim();
372-
}
373-
}
374-
}
375-
}
355+
return licenseFromElement;
376356
}
377357

378-
// Fall back to looking for licenseUrl
379-
var licenseUrlStart = content.IndexOf("<licenseUrl>", StringComparison.OrdinalIgnoreCase);
380-
if (licenseUrlStart >= 0)
381-
{
382-
licenseUrlStart += 12; // Skip '<licenseUrl>'
383-
var licenseUrlEnd = content.IndexOf("</licenseUrl>", licenseUrlStart, StringComparison.OrdinalIgnoreCase);
384-
if (licenseUrlEnd > licenseUrlStart)
385-
{
386-
var licenseUrl = content.Substring(licenseUrlStart, licenseUrlEnd - licenseUrlStart).Trim();
387-
// Extract license name from common URLs
388-
return ExtractLicenseFromUrl(licenseUrl);
389-
}
390-
}
358+
// Fall back to extracting from <licenseUrl> element
359+
return ExtractLicenseUrl(content);
391360
}
392361
catch (Exception)
393362
{
394363
// If we can't parse the nuspec, return null
395364
return null;
396365
}
366+
}
397367

398-
return null;
368+
private static string ExtractLicenseElement(string content)
369+
{
370+
var licenseStart = content.IndexOf("<license", StringComparison.OrdinalIgnoreCase);
371+
if (licenseStart < 0)
372+
{
373+
return null;
374+
}
375+
376+
var typeStart = content.IndexOf("type=\"", licenseStart, StringComparison.OrdinalIgnoreCase);
377+
if (typeStart < 0)
378+
{
379+
return null;
380+
}
381+
382+
typeStart += 6; // Skip 'type="'
383+
var typeEnd = content.IndexOf("\"", typeStart, StringComparison.OrdinalIgnoreCase);
384+
if (typeEnd <= typeStart)
385+
{
386+
return null;
387+
}
388+
389+
var licenseType = content.Substring(typeStart, typeEnd - typeStart);
390+
if (!licenseType.Equals("expression", StringComparison.OrdinalIgnoreCase))
391+
{
392+
return null;
393+
}
394+
395+
// Extract SPDX expression
396+
var contentStart = content.IndexOf(">", licenseStart) + 1;
397+
var contentEnd = content.IndexOf("</license>", contentStart, StringComparison.OrdinalIgnoreCase);
398+
if (contentEnd <= contentStart)
399+
{
400+
return null;
401+
}
402+
403+
return content.Substring(contentStart, contentEnd - contentStart).Trim();
404+
}
405+
406+
private static string ExtractLicenseUrl(string content)
407+
{
408+
var licenseUrlStart = content.IndexOf("<licenseUrl>", StringComparison.OrdinalIgnoreCase);
409+
if (licenseUrlStart < 0)
410+
{
411+
return null;
412+
}
413+
414+
licenseUrlStart += 12; // Skip '<licenseUrl>'
415+
var licenseUrlEnd = content.IndexOf("</licenseUrl>", licenseUrlStart, StringComparison.OrdinalIgnoreCase);
416+
if (licenseUrlEnd <= licenseUrlStart)
417+
{
418+
return null;
419+
}
420+
421+
var licenseUrl = content.Substring(licenseUrlStart, licenseUrlEnd - licenseUrlStart).Trim();
422+
// Extract license name from common URLs
423+
return ExtractLicenseFromUrl(licenseUrl);
399424
}
400425

401426
private static string ExtractLicenseFromUrl(string licenseUrl)

Philips.CodeAnalysis.Test/Security/LicenseAnalyzerTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,7 @@ public void Method(
705705
{
706706
// It's okay if this fails compilation due to syntax errors
707707
// The important thing is that the analyzer doesn't crash
708+
return;
708709
}
709710
}
710711

0 commit comments

Comments
 (0)