Skip to content

feat: implement core linting logic, rule analyzers, and CLI tooling w…#2

Merged
rahu619 merged 1 commit into
developfrom
feature/nuget-approach
Jul 2, 2026
Merged

feat: implement core linting logic, rule analyzers, and CLI tooling w…#2
rahu619 merged 1 commit into
developfrom
feature/nuget-approach

Conversation

@rahu619

@rahu619 rahu619 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

…hile removing deprecated project files.

Copilot AI review requested due to automatic review settings July 2, 2026 10:26
@rahu619 rahu619 merged commit 3be758c into develop Jul 2, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new SharpLinter architecture centered around a reusable SharpLinter.Core library (syntax-tree-based analyzers, configuration, providers, and output formatters) and a SharpLinter.Cli global tool, while removing the legacy LinterProject.* API/test artifacts.

Changes:

  • Adds the core lint engine, built-in/custom rule analyzers, configuration model, rule providers (bundled/cache/Microsoft Learn), and output formatters (console/json/sarif/msbuild).
  • Adds a System.CommandLine-based CLI with analyze, format, init, rules, and sync commands plus a CI workflow to build/test/pack.
  • Replaces old projects with new xUnit-based tests and a client verification project.

Reviewed changes

Copilot reviewed 77 out of 77 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
tests/SharpLinter.Core.Tests/SharpLinter.Core.Tests.csproj New xUnit test project for core + CLI integration tests.
tests/SharpLinter.Core.Tests/Rules/BuiltIn/AnalyzerTests.cs Adds unit tests for selected analyzers and custom rules loader.
tests/SharpLinter.Core.Tests/CliTests.cs Adds CLI command smoke tests via Program.Main.
tests/SharpLinter.ClientTest/SharpLinter.ClientTest.csproj Adds a “consumer” project intended to validate usage/build-time integration.
tests/SharpLinter.ClientTest/Program.cs Sample code with intentional violations for validation.
tests/SharpLinter.ClientTest/nuget.config Custom NuGet feed config for the client test project.
src/SharpLinter.Core/SharpLinter.Core.csproj New core library project with packaging metadata and dependencies.
src/SharpLinter.Core/Rules/RuleMetadata.cs Introduces rule metadata model used across analyzers/providers.
src/SharpLinter.Core/Rules/RuleCategory.cs Defines rule categories for filtering/grouping.
src/SharpLinter.Core/Rules/IRuleAnalyzer.cs Defines analyzer interface contract for built-in/custom analyzers.
src/SharpLinter.Core/Rules/Custom/PatternRuleAnalyzer.cs Implements regex-based custom “pattern” rules.
src/SharpLinter.Core/Rules/Custom/NamingRuleAnalyzer.cs Implements regex-based custom “naming” rules.
src/SharpLinter.Core/Rules/Custom/MetricRuleAnalyzer.cs Implements threshold-based custom “metric” rules.
src/SharpLinter.Core/Rules/Custom/CustomRuleLoader.cs YAML parsing and analyzer creation for custom rules.
src/SharpLinter.Core/Rules/BuiltIn/SL1012_StringConcatInLoopAnalyzer.cs Adds SL1012 built-in analyzer for string concat in loops.
src/SharpLinter.Core/Rules/BuiltIn/SL1011_PatternMatchingAnalyzer.cs Adds SL1011 built-in analyzer for pattern matching suggestions.
src/SharpLinter.Core/Rules/BuiltIn/SL1010_FileLengthAnalyzer.cs Adds SL1010 built-in analyzer for file length.
src/SharpLinter.Core/Rules/BuiltIn/SL1009_TrailingWhitespaceAnalyzer.cs Adds SL1009 built-in analyzer for trailing whitespace.
src/SharpLinter.Core/Rules/BuiltIn/SL1008_ConsistentBracePlacementAnalyzer Adds SL1008 built-in analyzer for brace placement consistency.
src/SharpLinter.Core/Rules/BuiltIn/SL1007_CyclomaticComplexityAnalyzer.cs Adds SL1007 built-in analyzer for cyclomatic complexity.
src/SharpLinter.Core/Rules/BuiltIn/SL1006_UnusedUsingAnalyzer.cs Adds SL1006 built-in analyzer for unused using directives (heuristic).
src/SharpLinter.Core/Rules/BuiltIn/SL1005_NamingConventionAnalyzer.cs Adds SL1005 built-in analyzer for naming conventions.
src/SharpLinter.Core/Rules/BuiltIn/SL1004_MethodLengthAnalyzer.cs Adds SL1004 built-in analyzer for method length.
src/SharpLinter.Core/Rules/BuiltIn/SL1003_PublicFieldAnalyzer.cs Adds SL1003 built-in analyzer for public fields.
src/SharpLinter.Core/Rules/BuiltIn/SL1002_EmptyCatchBlockAnalyzer.cs Adds SL1002 built-in analyzer for empty catch blocks.
src/SharpLinter.Core/Rules/BuiltIn/SL1001_AddBracesAnalyzer.cs Adds SL1001 built-in analyzer for missing braces.
src/SharpLinter.Core/Providers/RuleCacheManager.cs Adds JSON cache manager for provider-fetched rule metadata.
src/SharpLinter.Core/Providers/MicrosoftLearnRuleProvider.cs Adds Microsoft Learn HTML table scraper to build CA/IDE catalog.
src/SharpLinter.Core/Providers/IRuleProvider.cs Provider interface abstraction.
src/SharpLinter.Core/Providers/BundledRuleCatalog.cs Adds embedded “offline-first” bundled rule catalog provider.
src/SharpLinter.Core/Providers/bundled-rules.json Embedded bundled rules snapshot.
src/SharpLinter.Core/Output/SarifOutputFormatter.cs SARIF v2.1.0 output formatter.
src/SharpLinter.Core/Output/MsBuildOutputFormatter.cs MSBuild-style output formatter.
src/SharpLinter.Core/Output/JsonOutputFormatter.cs JSON output formatter.
src/SharpLinter.Core/Output/IOutputFormatter.cs Output formatter abstraction.
src/SharpLinter.Core/Output/ConsoleOutputFormatter.cs Console (colored) output formatter.
src/SharpLinter.Core/Formatting/CodeFormatter.cs Roslyn-based formatting wrapper.
src/SharpLinter.Core/Configuration/RuleOverride.cs Rule override model (severity + options).
src/SharpLinter.Core/Configuration/Presets.cs Built-in presets for rule severities/options.
src/SharpLinter.Core/Configuration/LintConfiguration.cs Config model + load/discover + option accessors.
src/SharpLinter.Core/Analysis/LintSeverity.cs Severity enum.
src/SharpLinter.Core/Analysis/LintResult.cs Lint run result model (diagnostics + counts + duration).
src/SharpLinter.Core/Analysis/LintEngine.cs Core orchestrator (loads analyzers, scans files, runs analysis/format).
src/SharpLinter.Core/Analysis/LintDiagnostic.cs Diagnostic model (rule/message/location/severity).
src/SharpLinter.Cli/SharpLinter.Cli.csproj CLI tool project with packaging/tooling metadata.
src/SharpLinter.Cli/Program.cs CLI entrypoint wiring commands.
src/SharpLinter.Cli/Commands/SyncCommand.cs Implements sync command.
src/SharpLinter.Cli/Commands/RulesCommand.cs Implements rules command including cache/bundled display.
src/SharpLinter.Cli/Commands/InitCommand.cs Implements init command to generate config templates.
src/SharpLinter.Cli/Commands/FormatCommand.cs Implements format command using the formatter wrapper.
src/SharpLinter.Cli/Commands/AnalyzeCommand.cs Implements analyze command and output selection.
SharpLinter.slnx New solution definition including src + tests.
README.md Adds product/usage documentation.
LICENSE Adds MIT license.
docs/rules.md Documents built-in rules catalog.
docs/custom-rules.md Documents YAML-based custom rules schema.
.sharplinter.rules.yaml Adds sample custom rules file.
.sharplinter.json Adds default config pointing to custom rules file.
.github/workflows/ci.yml Adds CI build/test/pack workflow.
LinterProject.Tests/Resources/Input/SampleCode_2.txt Removes deprecated legacy test fixture input.
LinterProject.Tests/Resources/Input/SampleCode_1.txt Removes deprecated legacy test fixture input.
LinterProject.Tests/Resources/Expected/SampleCode_2.txt Removes deprecated legacy expected output fixture.
LinterProject.Tests/Resources/Expected/SampleCode_1.txt Removes deprecated legacy expected output fixture.
LinterProject.Tests/LinterProject.Test.csproj Removes legacy test project.
LinterProject.Tests/LinterProject - Backup.Test.csproj Removes legacy backup test project file.
LinterProject.Tests/CodeAnalysisServiceTests.cs Removes legacy NUnit test suite.
LinterProject.sln Removes legacy solution.
LinterProject.API/SyntaxRewriters/AddBracesRewriter.cs Removes legacy API implementation detail.
LinterProject.API/Services/CodeAnalysisService.cs Removes legacy API formatter service.
LinterProject.API/Properties/launchSettings.json Removes legacy API launch settings.
LinterProject.API/Program.cs Removes legacy API host.
LinterProject.API/LinterProject.API.csproj Removes legacy API project.
LinterProject.API/Interfaces/ICodeAnalysisService.cs Removes legacy API interface.
LinterProject.API/ExceptionHandlingMiddleware.cs Removes legacy API middleware.
LinterProject.API/Controllers/CodeAnalysisController.cs Removes legacy API controller.
LinterProject.API/appsettings.json Removes legacy API config.
LinterProject.API/appsettings.Development.json Removes legacy API config.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +224 to +231
foreach (var pattern in _config.Exclude)
{
var normalizedPattern = pattern.Replace("**/", "");
if (relativePath.Contains(normalizedPattern.Trim('*', '/')))
{
return true;
}
}
Comment on lines +94 to +117
private void AnalyzeNumericLiterals(SyntaxNode root, string filePath, LintSeverity severity, List<LintDiagnostic> diagnostics)
{
var excludeSet = _config?.Exclude?.Select(e => e.ToString()).ToHashSet() ?? [];

foreach (var literal in root.DescendantNodes().OfType<LiteralExpressionSyntax>())
{
if (literal.IsKind(SyntaxKind.NumericLiteralExpression))
{
var text = literal.Token.ValueText;
if (!excludeSet.Contains(text))
{
// Only check within method bodies if scope is method-body
if (_config?.Scope == "method-body")
{
var inMethod = literal.Ancestors().Any(a =>
a is MethodDeclarationSyntax || a is ConstructorDeclarationSyntax);
if (!inMethod) continue;
}

AddDiagnostic(literal.GetLocation(), filePath, severity, diagnostics);
}
}
}
}
Comment on lines +72 to +80
// Check for: str += "something" or str += variable
if (assignment.IsKind(SyntaxKind.AddAssignmentExpression))
{
// Heuristic: if the right side is a string literal, interpolated string,
// or the left side is commonly named like a string builder pattern
if (IsLikelyStringExpression(assignment.Right) || IsLikelyStringExpression(assignment.Left))
{
ReportDiagnostic(assignment);
}
Comment on lines +80 to +90
public static LintConfiguration LoadFromFile(string filePath)
{
if (!File.Exists(filePath))
{
return Presets.GetPreset("recommended");
}

var json = File.ReadAllText(filePath);
var config = JsonSerializer.Deserialize<LintConfiguration>(json, JsonOptions);
return config ?? Presets.GetPreset("recommended");
}
Comment thread README.md
Comment on lines +177 to +183
"preset": "recommended",
"rules": {
"SL1001": "error",
"SL1004": { "severity": "warning", "maxLines": 60 },
"SL1007": { "severity": "suggestion", "maxComplexity": 15 },
"SL1010": "off"
},
Comment thread docs/rules.md

### SL1006: Potentially unused using directives
- **Default Severity:** Suggestion
- **Auto-Fixable:** Yes (via format command)
Comment on lines +10 to +13
<ItemGroup>
<!-- Consume our packed NuGet package -->
<PackageReference Include="SharpLinter" Version="1.0.0" />
</ItemGroup>
Comment on lines +60 to +65
// Act
var exitCode = await Program.Main(args);

// Assert
// Since we have a warning/error (SL1005 naming convention and SL1001 braces), exit code will depend on rules
var output = sw.ToString();
diagnostics.Should().ContainSingle();
diagnostics[0].RuleId.Should().Be("CUSTOM999");
}
}
Comment thread README.md
Comment on lines +59 to +60
### 3. Automatically Format & Fix Issues
Auto-fix fixable issues (like adding missing control flow braces or stripping trailing whitespaces):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants