Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .rat-excludes
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ _site/*

release-build-outcomes\.svg
release-workflow\.svg

# Exclude analyzer releases markdown files
AnalyzerReleases\..*\.md

19 changes: 19 additions & 0 deletions docs/images/release-build-outcomes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

This markup can be edited and converted to .svg or .png here:
https://www.mermaidchart.com/app/projects/95759d78-db93-499c-ad66-0e3f698ba88c/diagrams/31dbd6bc-7ec8-4583-a456-55e3fe3f6cfc/version/v0.1/edit

Expand Down
19 changes: 19 additions & 0 deletions docs/images/release-workflow.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

This markup can be edited and converted to .svg or .png here:
https://www.mermaidchart.com/app/projects/95759d78-db93-499c-ad66-0e3f698ba88c/diagrams/35faa26e-5ccf-4433-962e-32f20496471c/version/v0.1/edit

Expand Down
6 changes: 5 additions & 1 deletion docs/make-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,12 @@ Since Nerdbank.GitVersioning calculates the release version, the `AnalyzerReleas

`AnalyzerReleases.Shipped.md` evolves by appending each release as a new section. Each release is marked with a `## Release <version>` header.

> [!NOTE]
> Due to a limitation/bug in the Roslyn meta-analyzers, the Release header cannot contain semver pre-release labels (e.g., `-beta`, `-rc`, etc.).
> Therefore, the version token `{{vnext}}` is used to indicate the next minor release version, which will be replaced with the actual version during the git post-commit hook.

```markdown
## Release 2.0.0-alpha.1
## Release 2.0

### New Rules

Expand Down
8 changes: 4 additions & 4 deletions eng/git-hooks/post-commit
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ The 'nbgv' tool is required but not installed.
To recover manually:

1. Install the nbgv tool (see the docs/make-release.md documentation)
2. Run: nbgv get-version -v NuGetPackageVersion
2. Run: nbgv get-version -v MajorMinorVersion
3. In $file, replace the $token token with the version returned from step 2
4. Run: git add $file && git commit --amend --no-edit
5. Run: nbgv get-version -v NuGetPackageVersion again to ensure the version is the same as step 2 before proceeding
5. Run: nbgv get-version -v MajorMinorVersion again to ensure the version is the same as step 2 before proceeding
EOF
exit 1
fi

# Set flag to prevent recursion
export POST_COMMIT_RUNNING=1

# Get the NuGet version
version=$(nbgv get-version -v NuGetPackageVersion)
# Get the NuGet version without any prerelease suffix, which is not compatible with the Roslyn meta-analyzers
version=$(nbgv get-version -v MajorMinorVersion)
echo "Replacing '$token' with '$version' in '$file'"

# Replace {{vnext}} only in lines starting with "## Release "
Expand Down
42 changes: 35 additions & 7 deletions rat.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
directory as this script) as the target directory.

.PARAMETER Version
The version of Apache RAT to use (default: 0.13).
The version of Apache RAT to use (default: 0.16.1).
Comment thread
paulirwin marked this conversation as resolved.

.PARAMETER ExcludeFileName
Name of an exclude file containing path patterns that RAT should ignore.
Expand All @@ -43,19 +43,19 @@
.EXAMPLE
pwsh ./rat.ps1

Runs Apache RAT (default version 0.13) with exclusions from `rat-exclude.txt`.
Runs Apache RAT (default version 0.16.1) with exclusions from `rat-exclude.txt`.

.EXAMPLE
pwsh ./rat.ps1 -Version 0.13 -ExcludeFileName custom-exclude.txt
pwsh ./rat.ps1 -Version 0.16.1 -ExcludeFileName custom-exclude.txt

Runs Apache RAT version 0.13 using the specified exclude file.
Runs Apache RAT version 0.16.1 using the specified exclude file.

.NOTES
This script is intended for use by release managers when preparing official
ASF releases. It is not normally required for day-to-day development.
#>
param(
[string]$Version = "0.13",
[string]$Version = "0.16.1",
[string]$ExcludeFileName = ".rat-excludes"
)

Expand Down Expand Up @@ -90,13 +90,13 @@ if (-not (Test-Path $ratExcludeFile)) {

$argsList = @(
"-jar", $ratJar,
"--dir", "`"$scriptDir`"",
"--dir", "$scriptDir",
"--addLicense",
"--force"
)

if ($useExclude) {
$argsList += @("--exclude-file", "`"$ratExcludeFile`"")
$argsList += @("--exclude-file", "$ratExcludeFile")
}

# Call java with argument list. Use & to invoke program.
Expand All @@ -105,3 +105,31 @@ if ($useExclude) {
if ($LASTEXITCODE -ne 0) {
throw "RAT exited with code $LASTEXITCODE"
}

# Remove trailing whitespace from files modified by RAT
Write-Host "Removing trailing whitespace from modified files..."

# Get list of modified files from git
$modifiedFiles = git diff --name-only --diff-filter=M
if ($LASTEXITCODE -ne 0) {
Write-Host "Warning: Could not get modified files list from git."
} else {
foreach ($file in $modifiedFiles) {
if ([string]::IsNullOrWhiteSpace($file)) { continue }

$filePath = Join-Path $scriptDir $file
if (-not (Test-Path $filePath)) { continue }

try {
# Read all lines, trim trailing whitespace, and write back
$lines = Get-Content -Path $filePath
if ($null -ne $lines) {
$trimmedLines = $lines | ForEach-Object { $_.TrimEnd() }
$trimmedLines | Set-Content -Path $filePath -NoNewline:$false
Write-Host " Cleaned: $file"
}
} catch {
Write-Host " Warning: Could not process $file : $_"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,7 @@ under the License.
<value>Use {0}</value>
<comment>Title for code fix; {0} is the code element to utilize.</comment>
</data>
<data name="MakeXInternal" xml:space="preserve">
<value>Make {0} internal</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Lucene.Net.CodeAnalysis.Dev.CodeFixes;
using Lucene.Net.CodeAnalysis.Dev.CodeFixes.Utility;
using Lucene.Net.CodeAnalysis.Dev.Utility;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using SyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;

namespace Lucene.Net.CodeAnalysis.Dev;

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(LuceneDev1005_LuceneNetSupportPublicTypesCSCodeFixProvider)), Shared]
public class LuceneDev1005_LuceneNetSupportPublicTypesCSCodeFixProvider : CodeFixProvider
{
// Specify the diagnostic IDs of analyzers that are expected to be linked.
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } =
[Descriptors.LuceneDev1005_LuceneNetSupportPublicTypes.Id];

public override FixAllProvider? GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;

public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
// We link only one diagnostic and assume there is only one diagnostic in the context.
var diagnostic = context.Diagnostics.Single();

// 'SourceSpan' of 'Location' is the highlighted area. We're going to use this area to find the 'SyntaxNode' to rename.
var diagnosticSpan = diagnostic.Location.SourceSpan;

// Get the root of Syntax Tree that contains the highlighted diagnostic.
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

// Find SyntaxNode corresponding to the diagnostic.
var diagnosticNode = root?.FindNode(diagnosticSpan);

if (diagnosticNode is MemberDeclarationSyntax declaration)
{
var name = declaration switch
{
BaseTypeDeclarationSyntax baseTypeDeclaration => baseTypeDeclaration.Identifier.ToString(),
DelegateDeclarationSyntax delegateDeclaration => delegateDeclaration.Identifier.ToString(),
_ => null
};

if (name == null)
{
return;
}

// Register a code action that will invoke the fix.
context.RegisterCodeFix(
CodeActionHelper.CreateFromResource(
CodeFixResources.MakeXInternal,
createChangedSolution: c => MakeDeclarationInternal(context.Document, declaration, c),
"MakeDeclarationInternal",
name),
diagnostic);
}
}

private static async Task<Solution> MakeDeclarationInternal(Document document,
MemberDeclarationSyntax memberDeclaration,
CancellationToken cancellationToken)
{
var solution = document.Project.Solution;
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
if (semanticModel == null) return solution;

// Get the symbol for this type declaration
var symbol = semanticModel.GetDeclaredSymbol(memberDeclaration, cancellationToken);
if (symbol == null) return solution;

// Find all partial declarations of this symbol
var declaringSyntaxReferences = symbol.DeclaringSyntaxReferences;

// Update all partial declarations across all documents
foreach (var syntaxReference in declaringSyntaxReferences)
{
var declarationSyntax = await syntaxReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
if (declarationSyntax is not MemberDeclarationSyntax declaration) continue;

var declarationDocument = solution.GetDocument(syntaxReference.SyntaxTree);
if (declarationDocument == null) continue;

var syntaxRoot = await declarationDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if (syntaxRoot == null) continue;

// Get leading trivia from the first modifier (which contains license headers/comments)
var leadingTrivia = declaration.Modifiers.Count > 0
? declaration.Modifiers[0].LeadingTrivia
: SyntaxTriviaList.Empty;

// Get trailing trivia from the accessibility modifier we're removing (typically whitespace)
var accessibilityModifier = declaration.Modifiers
.FirstOrDefault(m => m.IsKind(SyntaxKind.PublicKeyword) ||
m.IsKind(SyntaxKind.InternalKeyword) ||
m.IsKind(SyntaxKind.ProtectedKeyword) ||
m.IsKind(SyntaxKind.PrivateKeyword));
var trailingTrivia = accessibilityModifier.TrailingTrivia;

// Remove existing accessibility modifiers
var newModifiers = SyntaxFactory.TokenList(
declaration.Modifiers
.Where(modifier => !modifier.IsKind(SyntaxKind.PrivateKeyword) &&
!modifier.IsKind(SyntaxKind.ProtectedKeyword) &&
!modifier.IsKind(SyntaxKind.InternalKeyword) &&
!modifier.IsKind(SyntaxKind.PublicKeyword))
).Insert(0, SyntaxFactory.Token(leadingTrivia, SyntaxKind.InternalKeyword, trailingTrivia)); // Ensure 'internal' is the first modifier with preserved trivia

var newDeclaration = declaration.WithModifiers(newModifiers);
var newRoot = syntaxRoot.ReplaceNode(declaration, newDeclaration);
solution = solution.WithDocumentSyntaxRoot(declarationDocument.Id, newRoot);
}

return solution;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,18 @@ public static CodeAction CreateFromResource(
var title = string.Format(resourceValue, args);
return CodeAction.Create(title, createChangedDocument, equivalenceKey);
}

/// <summary>
/// Create a CodeAction using a resource string and formatting arguments.
/// </summary>
public static CodeAction CreateFromResource(
string resourceValue,
Func<CancellationToken, Task<Solution>> createChangedSolution,
string equivalenceKey,
params object[] args)
{
var title = string.Format(resourceValue, args);
return CodeAction.Create(title, createChangedSolution, equivalenceKey);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ under the License.
<_PackageVersionPropsFilePath>$(_NuGetPackageOutputPath)\Lucene.Net.CodeAnalysis.Dev.Version.props</_PackageVersionPropsFilePath>
<!-- We install the analyzer package in a local directory so we don't pollute the
.nuget cache on the dev machine with temporary builds -->
<RestorePackagesPath>obj\LocalNuGetPackages</RestorePackagesPath>
<_RestorePackagesPath>$(RestorePackagesPath)\lucene.net.codeanalsis.dev</_RestorePackagesPath>
<RestorePackagesPath>obj/LocalNuGetPackages</RestorePackagesPath>
<_RestorePackagesPath>$(RestorePackagesPath)/lucene.net.codeanalysis.dev</_RestorePackagesPath>
</PropertyGroup>

<PropertyGroup Condition="Exists('$(_NuGetPackageOutputPath)')">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

namespace Lucene.Net.Support.BlockScoped
{
public class PublicClass
{
}

public interface PublicInterface
{
}

public enum PublicEnum
{
}

public delegate void PublicDelegate();

public struct PublicStruct
{
}

public record PublicRecord
{
}

public record struct PublicRecordStruct
{
}
}
Loading