Skip to content
Closed

Test #3870

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
54 changes: 54 additions & 0 deletions Flow.Launcher.Localization/.github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: build

on:
workflow_dispatch:
push:
branches: [ "main" ]
pull_request:

jobs:

build:

runs-on: windows-latest

env:
Dotnet_Version: 8.0.x
Project_Path: Flow.Launcher.Localization\Flow.Launcher.Localization.csproj

steps:

# Checkout codes
- name: Checkout
uses: actions/checkout@v4

# Install the .NET Core workload
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.Dotnet_Version }}

# Restore dependencies
- name: Restore dependencies
run: dotnet restore ${{ env.Project_Path }}

# Build the project
- name: Build
run: dotnet build ${{ env.Project_Path }} --configuration Release --no-restore

# Execute all unit tests in the solution
- name: Execute unit tests
if: github.event_name == 'push' && github.ref != 'refs/heads/main'
run: dotnet test --configuration Release --no-build

# Pack the NuGet package
- name: Create NuGet package
run: dotnet pack ${{ env.Project_Path }} --configuration Release --no-build --output nupkgs

# Upload the NuGet package
- name: Upload NuGet package
uses: actions/upload-artifact@v4
with:
name: Full nupkg
path: nupkgs/Flow.Launcher.Localization.*.nupkg
compression-level: 0
15 changes: 15 additions & 0 deletions Flow.Launcher.Localization/.github/workflows/pr_assignee.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Assign PR to creator

on:
pull_request_target:
types: [opened]

permissions:
pull-requests: write

jobs:
automation:
runs-on: ubuntu-latest
steps:
- name: Assign PR to creator
uses: toshimaru/[email protected]
61 changes: 61 additions & 0 deletions Flow.Launcher.Localization/.github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: publish

on:
workflow_dispatch:
push:
tags:
- '*'

jobs:

publish:

runs-on: windows-latest

env:
Dotnet_Version: 8.0.x
Project_Path: Flow.Launcher.Localization\Flow.Launcher.Localization.csproj

steps:

# Checkout codes
- name: Checkout
uses: actions/checkout@v4

# Install the .NET Core workload
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.Dotnet_Version }}

# Restore dependencies
- name: Restore dependencies
run: dotnet restore ${{ env.Project_Path }}

# Build the project
- name: Build
run: dotnet build ${{ env.Project_Path }} --configuration Release --no-restore

# Pack the NuGet package
- name: Create NuGet package
run: dotnet pack ${{ env.Project_Path }} --configuration Release --no-build --output nupkgs

# Publish to NuGet.org
- name: Push to NuGet
# if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: nuget push nupkgs\*.nupkg -source 'https://api.nuget.org/v3/index.json' -apikey ${{ secrets.NUGET_API_KEY }}

# Get package version
- name: Get Package Version
# if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
$version = [system.diagnostics.fileversioninfo]::getversioninfo("Flow.Launcher.Localization\bin\Release\netstandard2.0\Flow.Launcher.Localization.dll").fileversion
echo "release_version=$version" | out-file -filepath $env:github_env -encoding utf-8 -append

# Publish to GitHub releases
- name: Publish GitHub releases
# if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: softprops/action-gh-release@v1
with:
files: "nupkgs/*.nupkg"
tag_name: "v${{ env.release_version }}"
7 changes: 7 additions & 0 deletions Flow.Launcher.Localization/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.idea/
.vs/
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Flow.Launcher.Localization.Shared;
using Microsoft.CodeAnalysis;

namespace Flow.Launcher.Localization.Analyzers
{
public static class AnalyzerDiagnostics
{
public static readonly DiagnosticDescriptor OldLocalizationApiUsed = new DiagnosticDescriptor(
"FLAN0001",
"Old localization API used",
$"Use `{Constants.ClassName}.{{0}}({{1}})` instead",
"Localization",
DiagnosticSeverity.Warning,
isEnabledByDefault: true
);

public static readonly DiagnosticDescriptor ContextIsAField = new DiagnosticDescriptor(
"FLAN0002",
"Plugin context is a field",
"Plugin context must be at least internal static property",
"Localization",
DiagnosticSeverity.Error,
isEnabledByDefault: true
);

public static readonly DiagnosticDescriptor ContextIsNotStatic = new DiagnosticDescriptor(
"FLAN0003",
"Plugin context is not static",
"Plugin context must be at least internal static property",
"Localization",
DiagnosticSeverity.Error,
isEnabledByDefault: true
);

public static readonly DiagnosticDescriptor ContextAccessIsTooRestrictive = new DiagnosticDescriptor(
"FLAN0004",
"Plugin context property access modifier is too restrictive",
"Plugin context property must be at least internal static property",
"Localization",
DiagnosticSeverity.Error,
isEnabledByDefault: true
);

public static readonly DiagnosticDescriptor ContextIsNotDeclared = new DiagnosticDescriptor(
"FLAN0005",
"Plugin context is not declared",
$"Plugin context must be at least internal static property of type `{Constants.PluginContextTypeName}`",
"Localization",
DiagnosticSeverity.Error,
isEnabledByDefault: true
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
; Shipped analyzer releases
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
; Unshipped analyzer release
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
FLAN0001 | Localization | Warning | FLAN0001_OldLocalizationApiUsed
FLAN0002 | Localization | Error | FLAN0002_ContextIsAField
FLAN0003 | Localization | Error | FLAN0003_ContextIsNotStatic
FLAN0004 | Localization | Error | FLAN0004_ContextAccessIsTooRestrictive
FLAN0005 | Localization | Error | FLAN0005_ContextIsNotDeclared
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<RootNamespace>Flow.Launcher.Localization.Analyzers</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Flow.Launcher.Localization.Shared\Flow.Launcher.Localization.Shared.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System.Collections.Immutable;
using System.Linq;
using Flow.Launcher.Localization.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Flow.Launcher.Localization.Analyzers.Localize
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]

Check warning on line 11 in Flow.Launcher.Localization/Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

This compiler extension should not be implemented in an assembly containing a reference to Microsoft.CodeAnalysis.Workspaces. The Microsoft.CodeAnalysis.Workspaces assembly is not provided during command line compilation scenarios, so references to it could cause the compiler extension to behave unpredictably. (https://github.com/dotnet/roslyn-analyzers/blob/main/docs/rules/RS1038.md)
public class ContextAvailabilityAnalyzer : DiagnosticAnalyzer
{
#region DiagnosticAnalyzer

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
AnalyzerDiagnostics.ContextIsAField,
AnalyzerDiagnostics.ContextIsNotStatic,
AnalyzerDiagnostics.ContextAccessIsTooRestrictive,
AnalyzerDiagnostics.ContextIsNotDeclared
);

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
}

#endregion

#region Analyze Methods

private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var configOptions = context.Options.AnalyzerConfigOptionsProvider;
var useDI = configOptions.GetFLLUseDependencyInjection();
if (useDI)
{
// If we use dependency injection, we don't need to check for this context property
return;
}

var classDeclaration = (ClassDeclarationSyntax)context.Node;
var semanticModel = context.SemanticModel;
var pluginClassInfo = Helper.GetPluginClassInfo(classDeclaration, semanticModel, context.CancellationToken);
if (pluginClassInfo == null)
{
// Cannot find class that implements IPluginI18n
return;
}

// Context property is found, check if it's a valid property
if (pluginClassInfo.PropertyName != null)
{
if (!pluginClassInfo.IsStatic)
{
context.ReportDiagnostic(Diagnostic.Create(
AnalyzerDiagnostics.ContextIsNotStatic,
pluginClassInfo.CodeFixLocation
));
return;
}

if (pluginClassInfo.IsPrivate || pluginClassInfo.IsProtected)
{
context.ReportDiagnostic(Diagnostic.Create(
AnalyzerDiagnostics.ContextAccessIsTooRestrictive,
pluginClassInfo.CodeFixLocation
));
return;
}

// If the context property is valid, we don't need to check for anything else
return;
}

// Context property is not found, check if it's declared as a field
var fieldDeclaration = classDeclaration.Members
.OfType<FieldDeclarationSyntax>()
.SelectMany(f => f.Declaration.Variables)
.Select(f => semanticModel.GetDeclaredSymbol(f))
.FirstOrDefault(f => f is IFieldSymbol fs && fs.Type.Name is Constants.PluginContextTypeName);
var parentSyntax = fieldDeclaration
?.DeclaringSyntaxReferences[0]
.GetSyntax()
.FirstAncestorOrSelf<FieldDeclarationSyntax>();
if (parentSyntax != null)
{
context.ReportDiagnostic(Diagnostic.Create(
AnalyzerDiagnostics.ContextIsAField,
parentSyntax.GetLocation()
));
return;
}

// Context property is not found, report an error
context.ReportDiagnostic(Diagnostic.Create(
AnalyzerDiagnostics.ContextIsNotDeclared,
classDeclaration.Identifier.GetLocation()
));
}

#endregion
}
}
Loading
Loading