Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FLLUseDependencyInjection property group & Move all constants to Shared project #18

Merged
merged 4 commits into from
Mar 10, 2025

Conversation

Jack251970
Copy link
Collaborator

@Jack251970 Jack251970 commented Mar 10, 2025

Add FLLUseDependencyInjection property group

Since InternationalizationManager.Instance is on the way to be deprecated (Flow-Launcher/Flow.Launcher#3276), we should move to Ioc.Default.GetRequiredService.

To let this can be used for not only core project, we should use property FLLUseDependencyInjection instead of core assembly check. The default value is false.

Move all constants to Shared project

Improve code quality.

Test

When we add these in the project

<!-- declare the property you want to access in your analyzer -->
<PropertyGroup>
  <FLLUseDependencyInjection>true</FLLUseDependencyInjection>
</PropertyGroup>

Source generator will use dependency injection to get translation

image

And you do not need to have public static Context in your main class. (Tested with no build issue & No warning)

image

@Jack251970 Jack251970 requested a review from Yusyuriv March 10, 2025 04:09
@Jack251970 Jack251970 added the enhancement New feature or request label Mar 10, 2025
Copy link
Contributor

coderabbitai bot commented Mar 10, 2025

📝 Walkthrough

Walkthrough

This pull request introduces a new shared project for localization, adding centralized constants and helper methods while updating analyzer and source generator projects to reference this shared project. The changes refactor hardcoded strings to use a new Constants class and integrate dependency injection configuration checks into the analyzer and source generator logic. Additionally, minor formatting adjustments and cleanup of extraneous lines have been applied to maintain code consistency.

Changes

Files Summary
Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj
Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj
Flow.Launcher.Localization/Flow.Launcher.Localization.csproj
Flow.Launcher.Localization.slnx
Added project references to the shared project and included it in the solution. In the main project file, new None items for the shared DLL and properties were introduced.
Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs
Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs
Replaced hardcoded constant strings with references to the centralized Constants class. Added a dependency injection (DI) configuration check in ContextAvailabilityAnalyzer and removed an extraneous empty line.
Flow.Launcher.Localization.Shared/Constants.cs
Flow.Launcher.Localization.Shared/Helper.cs
Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj
Introduced a new shared project comprising a Constants class with localization constants and a Helper class for DI configuration retrieval, along with its dedicated project file.
Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs Refactored usage of string constants to utilize the Constants class. Modified DI configuration logic in the execution flow and simplified the localization method signature.

Sequence Diagram(s)

sequenceDiagram
    participant Analyzer
    participant Config as AnalyzerConfigOptionsProvider
    Analyzer->>Config: Retrieve "FLLUseDependencyInjection" value
    alt DI Enabled
        Analyzer-->>Analyzer: Exit early (skip further context analysis)
    else DI Disabled
        Analyzer->>Analyzer: Continue checking context properties using Constants
    end
Loading
sequenceDiagram
    participant Generator
    participant Config as AnalyzerConfigOptionsProvider
    Generator->>Config: Retrieve "FLLUseDependencyInjection" value
    alt DI Enabled
        Generator-->>Generator: Use DI configuration to generate localization methods
    else DI Disabled
        Generator->>Generator: Retrieve pluginInfo and generate methods with Constants
    end
Loading

Possibly related PRs

  • Resolve namespace prefix dynamically #15: The changes in the main PR are related to modifications in the LocalizeSourceGenerator.cs file, as both involve updates to constants and handling of dependency injection in the source generation logic.
  • Fix Index Issue for Format String & Add Culture Info When Need to Format #17: The changes in the main PR involve adding a project reference to shared constants, which relates to modifications in the LocalizeSourceGenerator class that utilize constants defined in the newly introduced Constants class.
  • Include analyzers in the build #5: The changes in the main PR involve adding a project reference to Flow.Launcher.Localization.Shared.csproj, which relates to the retrieved PR that also modifies the Flow.Launcher.Localization.csproj file by updating project references.

Poem

I'm a rabbit with a codey hop,
Refactoring constants until I drop.
With shared projects and DI in play,
My lines of code brighten up the day.
Bugs and clutters scatter away —
A merry dance in code's ballet!
(_/)(◕‿◕) Hop on!


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs (2)

79-83: Nested tuple complexity
Deeply nested tuples can harm readability. A small record or class might be more maintainable for passing multiple elements.


693-693: Negated condition readability
Consider simplifying if (!(string.IsNullOrEmpty(getTranslation))) to the more typical form below.

-if (!(string.IsNullOrEmpty(getTranslation)))
+if (!string.IsNullOrEmpty(getTranslation))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8496ab and 5989c43.

📒 Files selected for processing (10)
  • Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj (1 hunks)
  • Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs (5 hunks)
  • Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs (0 hunks)
  • Flow.Launcher.Localization.Shared/Constants.cs (1 hunks)
  • Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj (1 hunks)
  • Flow.Launcher.Localization.Shared/Helper.cs (1 hunks)
  • Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj (1 hunks)
  • Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs (14 hunks)
  • Flow.Launcher.Localization.slnx (1 hunks)
  • Flow.Launcher.Localization/Flow.Launcher.Localization.csproj (1 hunks)
💤 Files with no reviewable changes (1)
  • Flow.Launcher.Localization.Analyzers/Localize/OldGetTranslateAnalyzerCodeFixProvider.cs
🔇 Additional comments (27)
Flow.Launcher.Localization.slnx (1)

3-3: Solution structure correctly updated to include new Shared project.

The addition of the Shared project to the solution file aligns with the PR objectives to centralize constants and facilitate dependency injection configuration.

Flow.Launcher.Localization.SourceGenerators/Flow.Launcher.Localization.SourceGenerators.csproj (1)

18-20: Project reference to Shared project correctly added.

The Source Generators project now properly references the Shared project, allowing access to centralized constants and the dependency injection configuration helper.

Flow.Launcher.Localization.Analyzers/Flow.Launcher.Localization.Analyzers.csproj (1)

19-21: Project reference to Shared project correctly added.

The Analyzers project now properly references the Shared project, allowing access to centralized constants and the dependency injection configuration helper.

Flow.Launcher.Localization.Shared/Helper.cs (1)

1-17: Helper extension method implemented correctly.

The implementation of GetFLLUseDependencyInjection extension method for AnalyzerConfigOptionsProvider correctly retrieves the configuration property and defaults to false when not specified. This facilitates the transition from InternationalizationManager.Instance to dependency injection as outlined in the PR objectives.

Flow.Launcher.Localization.Shared/Flow.Launcher.Localization.Shared.csproj (1)

1-14: Well-structured shared project configuration

The new shared project is properly configured with appropriate settings for a .NET Standard 2.0 library that will be referenced by analyzer projects. The use of EnforceExtendedAnalyzerRules property is good practice for Roslyn-related components.

Flow.Launcher.Localization/Flow.Launcher.Localization.csproj (2)

19-21: Correctly added reference to the new shared project

The project reference to the new Shared project has been added with appropriate PrivateAssets configuration, which is consistent with the other project references.


33-37: Properly including the shared DLL in the package

The shared DLL is correctly added to the package with the same configuration as the other DLLs, ensuring it will be available to consumers of the package.

Flow.Launcher.Localization.Shared/Constants.cs (1)

1-18: Good centralization of constants

Moving these constants to a shared project improves maintainability and reduces duplication across the codebase. The organization of constants is clean and well-structured.

One note: the regex for LanguagesXamlRegex is using a compiled pattern which is generally good for performance since this regex will likely be used repeatedly.

Flow.Launcher.Localization.Analyzers/Localize/ContextAvailabilityAnalyzer.cs (5)

3-3: Appropriate usage of the shared namespace

The addition of the using statement for the shared namespace allows clean access to the centralized constants.


30-34: Well-implemented dependency injection check

This code correctly implements the PR objective to add dependency injection support. The early return pattern is efficient and prevents unnecessary processing when dependency injection is enabled.


44-44: Replaced hardcoded string with constant reference

Good refactoring to use the constant from the shared project instead of a hardcoded string.


73-73: Replaced hardcoded string with constant reference

Good refactoring to use the constant from the shared project instead of a hardcoded string.


95-95: Replaced hardcoded string with constant reference

Good refactoring to use the constant from the shared project instead of a hardcoded string.

Flow.Launcher.Localization.SourceGenerators/Localize/LocalizeSourceGenerator.cs (14)

8-8: Centralized dependencies
Referencing the shared localization library is a good step towards removing magic strings in this generator.


12-12: New reference for analyzer diagnostics
Adding using Microsoft.CodeAnalysis.Diagnostics; appears valid and aligns with incremental generator requirements.


41-41: Use of a centralized regex
Replacing the inline pattern with Constants.LanguagesXamlRegex improves maintainability and consistency.


66-68: Loading analyzer config
Introducing AnalyzerConfigOptionsProvider into the pipeline is a fine approach. Consider how the code behaves if the config is missing or returns unexpected values.

Would you like a script to check code references for fallback logic to handle missing config?


104-105: Dependency injection flag
Retrieving FLLUseDependencyInjection from AnalyzerConfig ensures the default value is used correctly. Please verify the fallback scenario remains as intended.


106-111: Conditional plugin info retrieval
Bypassing plugin info when using DI fits your design goals, avoiding unnecessary property checks.


154-158: Centralized URIs
Substituting Constants.SystemPrefixUri and Constants.XamlPrefixUri removes hardcoded strings for clarity and consistency.


178-185: Using Constants.XamlTag and Constants.KeyTag
Referring to these constants avoids string typos and promotes consistent usage across the project.


423-423: Class name check
Checking whether parts[0] equals Constants.ClassName helps ensure the generator only processes valid calls.


439-439: Plugin interface name
Utilizing Constants.PluginInterfaceName instead of a raw string is safer and more coherent.


447-447: Context type name
The move to Constants.PluginContextTypeName helps avoid mistakes and aligns with the broader constants-based strategy.


600-613: Static Api property with DI
Acquiring IPublicAPI via dependency injection is neatly implemented. If multiple threads access this static property in parallel, consider verifying thread safety.

Would you like a script to check for parallel usage references of this property?


624-625: Doc comments and translation method
These lines neatly tie in the new translation approach while generating doc comments.


630-630: Constant-based output file name
Using ${Constants.ClassName}.{assemblyName}.g.cs for your generated source is an excellent way to unify naming.

Copy link
Member

@Yusyuriv Yusyuriv left a comment

Choose a reason for hiding this comment

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

I left a few comments and also added a file. With that file, there's no need for the users of this package to manually specify

<CompilerVisibleProperty Include="FLLUseDependencyInjection" />

in their projects, it will be available by default. Please check out the comments and verify that on your end it also now works without manually specifying CompilerVisibleProperty.

var configOptions = data.Item1.Item1.ConfigOptionsProvider;
var pluginClasses = data.Item1.Item1.Item1.PluginClassInfos;
var usedKeys = data.Item1.Item1.Item1.Item1.InvocationKeys;
var localizedStrings = data.Item1.Item1.Item1.Item1.LocalizableStrings;
Copy link
Member

Choose a reason for hiding this comment

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

I think those Item1 are getting out of hand. Isn't there a way to access them by their actual names?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I really do not know how to name those things, like ((((ImmutableArray<LocalizableString> LocalizableStrings, ImmutableHashSet<string> InvocationKeys), ImmutableArray<PluginClassInfo> PluginClassInfos), AnalyzerConfigOptionsProvider ConfigOptionsProvider), Compilation Compilation) such type.

image

Use Others or Left? I have no idea. If you have any good name for me, please let me know.

Copy link
Member

Choose a reason for hiding this comment

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

I was just curious if it's possible to avoid using tuples altogether and just use a record:

private void Execute(SourceProductionContext context, GeneratorInputs data)
{

I don't have in-depth knowledge about source generators, so I don't know if it's possible or not. Let's leave it as is for now, and just remember that this is something that should probably change in the future.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It seems that .NetCore2.0 cannot support record....

@Jack251970
Copy link
Collaborator Author

I left a few comments and also added a file. With that file, there's no need for the users of this package to manually specify

<CompilerVisibleProperty Include="FLLUseDependencyInjection" />

in their projects, it will be available by default. Please check out the comments and verify that on your end it also now works without manually specifying CompilerVisibleProperty.

It works well on my device.

@Jack251970
Copy link
Collaborator Author

I left a few comments and also added a file. With that file, there's no need for the users of this package to manually specify

<CompilerVisibleProperty Include="FLLUseDependencyInjection" />

in their projects, it will be available by default. Please check out the comments and verify that on your end it also now works without manually specifying CompilerVisibleProperty.

Do you think we also need to add <ItemGroup> <AdditionalFiles Include="Languages\en.xaml" /> </ItemGroup> into .props file?

Developers do not need to add this file manually since this is the default place for xaml language file.

@Yusyuriv
Copy link
Member

Do you think we also need to add <ItemGroup> <AdditionalFiles Include="Languages\en.xaml" /> </ItemGroup> into .props file?

Are we assuming that English is always going to be the default language? I think it's a pretty safe assumption to have, so yeah, we should add it to the .props file.

@Jack251970
Copy link
Collaborator Author

Jack251970 commented Mar 10, 2025

Do you think we also need to add <ItemGroup> <AdditionalFiles Include="Languages\en.xaml" /> </ItemGroup> into .props file?

Are we assuming that English is always going to be the default language? I think it's a pretty safe assumption to have, so yeah, we should add it to the .props file.

IIRC, FL sets English as the default language. So all plugins should provide English strings.

@Jack251970
Copy link
Collaborator Author

Jack251970 commented Mar 10, 2025

@Yusyuriv Or, one more thing. Because I config Flow.Launcher.Localization.Shared project as other analyzers project, it will also occur in the analyzer list.

image

I have tried to add <ProjectReference Include="..\Flow.Launcher.Localization.Shared\Flow.Launcher.Localization.Shared.csproj" > into main project, but the NuGet package will not add Shared project.

I have also checked this configuration:

<None Include="$(OutputPath)\Flow.Launcher.Localization.Shared.dll">
  <Pack>true</Pack>
  <PackagePath>lib\netstandard2.0</PackagePath>
  <Visible>false</Visible>
</None>

And it cannot work either.

@Yusyuriv
Copy link
Member

I don't think it being added as an analyzer is a problem. It doesn't actually contain any analyzers, so it doesn't do anything, and this project will be installed as a dependency only during development of plugins, it won't get published alongside the plugin.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
Flow.Launcher.Localization/build/Flow.Launcher.Localization.props (3)

3-3: Consider adding a comment explaining the property's purpose.

While the implementation is correct, adding a comment explaining that FLLUseDependencyInjection controls whether to use dependency injection or the static instance would improve maintainability and help future developers understand the purpose of this property.

-        <CompilerVisibleProperty Include="FLLUseDependencyInjection" />
+        <!-- Controls whether to use Ioc.Default.GetRequiredService (true) or InternationalizationManager.Instance (false) -->
+        <CompilerVisibleProperty Include="FLLUseDependencyInjection" />

4-4: Consider documenting the expected file path structure.

The hardcoded path Languages\en.xaml assumes a specific project structure. Consider adding documentation or a comment to clarify this assumption for users of the package.

-        <AdditionalFiles Include="Languages\en.xaml" />
+        <!-- Default English language file - place your localization files in a "Languages" folder at your project root -->
+        <AdditionalFiles Include="Languages\en.xaml" />

2-5: Consider adding a PropertyGroup for the default property value.

The PR objectives mention that FLLUseDependencyInjection has a default value of false, but this isn't explicitly set in the file. Consider adding a PropertyGroup to define this default value.

 <Project>
+    <PropertyGroup>
+        <FLLUseDependencyInjection>false</FLLUseDependencyInjection>
+    </PropertyGroup>
     <ItemGroup>
         <CompilerVisibleProperty Include="FLLUseDependencyInjection" />
         <AdditionalFiles Include="Languages\en.xaml" />
     </ItemGroup>
 </Project>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ce1201 and fdf2cb1.

📒 Files selected for processing (1)
  • Flow.Launcher.Localization/build/Flow.Launcher.Localization.props (1 hunks)
🔇 Additional comments (1)
Flow.Launcher.Localization/build/Flow.Launcher.Localization.props (1)

1-6: Good implementation of automatic property configuration.

This props file effectively adds the FLLUseDependencyInjection compiler visible property and sets up the default English language file, which aligns well with the PR objectives to simplify adoption of dependency injection and standardize localization across projects.

@Jack251970
Copy link
Collaborator Author

Thanks for your quick review👍

@Jack251970 Jack251970 merged commit 61fed01 into main Mar 10, 2025
2 checks passed
@Jack251970 Jack251970 deleted the use_dependency_injection branch March 10, 2025 10:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants