Implement LuceneDev6001, 6002, 6003 Analyzers & CodeFixes with Unit Tests (#14)

* Add analyzers, codefixes, sample and test files for 6001, 6002, 6003

* feat(analyzers): smart Span fixes, char optimizations,NRT updatesand add Documentation as per suggestion

* Address LuceneDev600x review feedback and fix tests

- LuceneDev6003 code fix: use getInnermostNodeForTie + descendant
  fallback so FindNode resolves to the LiteralExpressionSyntax.
- LuceneDev6003 analyzer: detect char overload correctly for spans.
  ReadOnlySpan<T>.IndexOf(T) / LastIndexOf(T) are MemoryExtensions
  extensions, so the previous search on the containing type missed
  them. StartsWith/EndsWith intentionally remain excluded (no char
  overload exists for spans).
- LuceneDev6001 analyzer: pass the invalid StringComparison value
  name to Diagnostic.Create so the {1} placeholder in the message
  format is substituted (previously rendered as literal "{1}").
- LuceneDev6001 code fix: use continue instead of return inside the
  diagnostic loop so multiple diagnostics in one file all get fixes
  offered.
- Sample project: uncomment violating examples so the diagnostics
  fire live in the IDE (matches the existing LuceneDevXxxxSample
  convention). Add .editorconfig to downgrade error-severity rules
  to warning in the sample project so it still compiles.
- LuceneDev6003 sample: rewrite to use the analyzer's target methods
  (IndexOf/LastIndexOf/StartsWith/EndsWith) rather than string.Equals,
  including a ReadOnlySpan<char> example.
- Clean up excessive blank lines in 6002 code fix and a stray
  trailing space in a variable name.
- Update 6001 tests to include the comparison-value argument.
- Fix off-by-one spans in 6003 code fix tests and add a span test.

* Renumber LuceneDev6xxx rules to contiguous IDs

Replace the underscore-suffixed IDs (6001_1, 6001_2, 6002_1, 6002_2)
with contiguous numeric IDs matching the rest of the Lucene.NET
analyzer taxonomy:

  6001_1 -> 6001  Missing StringComparison on String overload
  6001_2 -> 6002  Invalid StringComparison on String overload
  6002_1 -> 6003  Redundant Ordinal on span overload
  6002_2 -> 6004  Invalid StringComparison on span overload
  6003   -> 6005  Single-character string literal

Each analyzer class still bundles the two related diagnostics that
share symbol resolution; files are named with the ID range
(e.g., LuceneDev6001_6002_StringComparisonAnalyzer.cs) and the
LuceneDev6005 analyzer stands alone.

Update Descriptors, Resources.resx, AnalyzerReleases.Unshipped.md,
DiagnosticCategoryAndIdRanges.txt, samples, editorconfig overrides,
and tests to reference the new IDs. Tighten the 6005 summary doc
to note that spans only have char overloads for IndexOf/LastIndexOf.

---------

Co-authored-by: Paul Irwin <paulirwin@gmail.com>
23 files changed
tree: ca709c8d4c4e86f8cafd5bbbe9ad65b3889b2f23
  1. .github/
  2. branding/
  3. docs/
  4. eng/
  5. src/
  6. tests/
  7. .asf.yaml
  8. .editorconfig
  9. .gitattributes
  10. .gitignore
  11. .rat-excludes
  12. DiagnosticCategoryAndIdRanges.txt
  13. Directory.Build.props
  14. Directory.Build.targets
  15. Directory.Packages.props
  16. global.json
  17. LICENSE.txt
  18. Lucene.Net.CodeAnalysis.Dev.ChildProcessDbgSettings
  19. Lucene.Net.CodeAnalysis.Dev.sln
  20. NOTICE.txt
  21. rat.ps1
  22. README.md
  23. renovate.json
  24. version.json
README.md

Apache Lucene.NET Dev Analyzers

This repo contains custom Roslyn analyzers that are used by the Apache Lucene.NET project to enforce code quality and consistency, as well as provide automated code fixes.

These analyzers are intended for use by contributors to the Lucene.NET project only. They are not intended for public use outside of this project. Therefore, any releases or NuGet packages produced from this repository are not official Apache Lucene.NET project artifacts, and are not subject to the same quality control or testing as the official Lucene.NET releases. They are also not subject to the release policy or voting process, as these are not intended to be used “beyond the group that owns it.”

Building

To build the analyzers, you will need to have the .NET 8 SDK installed.

To build from the repo root, run the following command:

dotnet build

To run the tests, you can use the following command:

dotnet test

IDE Support and Debugging

These analyzers have been tested with Visual Studio 2022 and JetBrains Rider. They should work with any IDE that supports Roslyn analyzers, but your mileage may vary. Importantly, they also work with MSBuild, so they can be used in our CI pipelines, or to help validate your changes when you build before submitting a pull request.

A Lucene.Net.CodeAnalysis.Dev.Sample project has been provided to demonstrate and debug the analyzers and code fixes in the IDE during development of them. After building, you should notice the analyzers producing the expected warnings in the Sample project. You can also debug the analyzers by setting a breakpoint in your analyzer and launching the DebugRoslynAnalyzers target of the Lucene.Net.CodeAnalysis.Dev project. You can also debug them by debugging the unit tests.

Contributing

Please read and follow the Apache Lucene.NET Contributor's Guide first before proceeding further.

Reserving a Diagnostic ID

Before creating any analyzers, you'll need a reserved diagnostic ID for your analyzer(s). To avoid multiple contributors attempting to use the same ID at the same time, we have created a simple process to follow. It is important that you follow this process to avoid rework of your PR.

  1. Make sure there is an issue on the main Apache Lucene.NET repo for the analyzer(s) needed, that has been approved by the Lucene.NET team as indicated by having the approved-rule label.
  2. Reserve your diagnostic ID(s) before implementing the analyzer(s):
    • If you are a Lucene.NET committer, you can reserve one yourself. Modify the DiagnosticCategoryAndIdRanges.txt file (following the instructions in that file) to reserve your ID(s). Commit and push the change to this file directly to the main branch, as the only file in the commit. DO NOT include any other code or changes in this commit. In the event of a conflict, do not merge this file; discard your changes, pull latest, and try again. Include the issue number in your commit message.
    • If you are not a Lucene.NET committer, request in the discussion for the GitHub issue that a committer do the steps above for you for your desired number of diagnostic IDs. Please make sure to mention which category the ID(s) should belong to.
  3. Once you have the reserved ID(s), you can proceed with implementing your analyzer and submitting a pull request. Make sure to include your analyzer in the AnalyzerReleases.Unshipped.md file.

Requirements

Before submitting a pull request to this repo, ensure that each analyzer you're adding:

  1. Has a reserved ID (see above)
  2. Has an entry in the AnalyzerReleases.Unshipped.md file, reflowing the table if needed
  3. Matches existing analyzer naming conventions and code styles
  4. Has a title, description, and message format resource in the Resources.resx file (currently English only)
  5. Has a working, sample violation in the Lucene.Net.CodeAnalysis.Dev.Sample project
  6. Has good unit test coverage in the Lucene.Net.CodeAnalysis.Dev.Tests project, using existing styles and practices per the other unit tests there