add a scanner, but this seems to be a wrong solution. Change open-source head

This commit is contained in:
Youmu Liu
2026-07-07 18:20:38 +08:00
parent b053567eb7
commit 1705d7c245
276 changed files with 3468 additions and 7205 deletions
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="PanelStateChangeBindingAttribute"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
@@ -14,11 +21,11 @@ namespace StgSharp.UserInterface
{
public string StatePath { get; } = string.IsNullOrWhiteSpace(statePath) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(statePath)) :
throw new ArgumentException("Value cannot be null or whitespace.", nameof(statePath)) :
statePath;
public string PanelHostPath { get; } = string.IsNullOrWhiteSpace(panelHostPath) ?
throw new ArgumentException("Value cannot be null or whitespace.", nameof(panelHostPath)) :
throw new ArgumentException("Value cannot be null or whitespace.", nameof(panelHostPath)) :
panelHostPath;
}
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="PanelStateNodeAttribute"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
namespace StgSharp.UserInterface
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="Service.Host"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="Service.LoadAccomplishmentEvent"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
namespace StgSharp.UserInterface
{
public sealed record ServiceLoadAccomplishmentEvent
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="Service.LoadCommand"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="State.AppState"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="State.FrontCommandHost"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="State.Host"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="State.PanelState"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="State.ServiceManager"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="View.CommandResult"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
namespace StgSharp.UserInterface
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="View.ExecuteCommand"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="View.Host"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="View.StateChangeCommand"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
namespace StgSharp.UserInterface
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="View.StateValueCommand"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
namespace StgSharp.UserInterface
@@ -6,9 +13,10 @@ namespace StgSharp.UserInterface
{
public StateValueCommand(
string statePath,
TValue value
) : base(statePath)
string statePath,
TValue value
)
: base(statePath)
{
Value = value;
}
@@ -1,50 +1,57 @@
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.Analysis"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace StgSharp.UserInterface.Generator;
internal static class PanelStateIncrementalGeneratorAnalysis
namespace StgSharp.UserInterface.Generator
{
public static PanelStateIncrementalGeneratorOutput Analyze(
PanelStateIncrementalGeneratorInput input
)
internal static class PanelStateIncrementalGeneratorAnalysis
{
if (input.TypeTargets.IsDefaultOrEmpty)
{
return new PanelStateIncrementalGeneratorOutput(
input.Compilation,
ImmutableArray<PanelStateIncrementalGeneratorTypeAnalysis>.Empty);
}
HashSet<string> emittedTypes = new(StringComparer.Ordinal);
ImmutableArray<PanelStateIncrementalGeneratorTypeAnalysis>.Builder builder =
ImmutableArray.CreateBuilder<PanelStateIncrementalGeneratorTypeAnalysis>();
foreach (PanelStateIncrementalGeneratorTypeTarget target in input.TypeTargets
.OrderBy(static item => item.TypeDisplayName, StringComparer.Ordinal))
public static PanelStateIncrementalGeneratorOutput Analyze(
PanelStateIncrementalGeneratorInput input
)
{
if (!emittedTypes.Add(target.TypeDisplayName))
{
continue;
if (input.TypeTargets.IsDefaultOrEmpty) {
return new PanelStateIncrementalGeneratorOutput(
input.Compilation,
ImmutableArray<PanelStateIncrementalGeneratorTypeAnalysis>.Empty);
}
PanelStateSymbolPartAnalysis stateSymbols = PanelStateIncrementalGeneratorStateSymbols.Analyze(target);
StateChangeBindingPartAnalysis stateChangeBindings = PanelStateIncrementalGeneratorStateChangeBindings.Analyze(target);
HashSet<string> emittedTypes = new(StringComparer.Ordinal);
ImmutableArray<PanelStateIncrementalGeneratorTypeAnalysis>.Builder builder =
ImmutableArray.CreateBuilder<PanelStateIncrementalGeneratorTypeAnalysis>();
builder.Add(
new PanelStateIncrementalGeneratorTypeAnalysis(
target,
stateSymbols,
stateChangeBindings,
PanelStateIncrementalGeneratorStateCommandHandlers.Analyze(
target,
stateSymbols,
stateChangeBindings)));
foreach (PanelStateIncrementalGeneratorTypeTarget target in input.TypeTargets
.OrderBy(static item => item.TypeDisplayName, StringComparer.Ordinal))
{
if (!emittedTypes.Add(target.TypeDisplayName))
{
continue;
}
PanelStateSymbolPartAnalysis stateSymbols = PanelStateIncrementalGeneratorStateSymbols.Analyze(target);
StateChangeBindingPartAnalysis stateChangeBindings = PanelStateIncrementalGeneratorStateChangeBindings.Analyze(target);
builder.Add(
new PanelStateIncrementalGeneratorTypeAnalysis(target, stateSymbols,
stateChangeBindings,
PanelStateIncrementalGeneratorStateCommandHandlers.Analyze(
target,
stateSymbols,
stateChangeBindings)));
}
return new PanelStateIncrementalGeneratorOutput(
input.Compilation,
builder.ToImmutable());
}
return new PanelStateIncrementalGeneratorOutput(
input.Compilation,
builder.ToImmutable());
}
}
@@ -1,6 +1,16 @@
namespace StgSharp.UserInterface.Generator;
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.Diagnostics"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
internal static class PanelStateIncrementalGeneratorDiagnostics
namespace StgSharp.UserInterface.Generator
{
public const string Category = "StgSharp.UserInterface.Generator";
internal static class PanelStateIncrementalGeneratorDiagnostics
{
public const string Category = "StgSharp.UserInterface.Generator";
}
}
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.Emitter"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Linq;
@@ -31,8 +38,8 @@ namespace StgSharp.UserInterface.Generator
foreach (string typeName in source.TypeAnalyses
.Select(static analysis => analysis.Target.TypeDisplayName)
.Distinct()
.OrderBy(static name => name, StringComparer.Ordinal))
.Distinct()
.OrderBy(static name => name, StringComparer.Ordinal))
{
_ = builder.Append(" \"");
_ = builder.Append(typeName.Replace("\"", "\"\"", StringComparison.Ordinal));
@@ -45,7 +52,7 @@ namespace StgSharp.UserInterface.Generator
_ = builder.AppendLine(" {");
foreach (PanelStateIncrementalGeneratorTypeAnalysis analysis in source.TypeAnalyses
.OrderBy(static item => item.Target.TypeDisplayName, StringComparer.Ordinal))
.OrderBy(static item => item.Target.TypeDisplayName, StringComparer.Ordinal))
{
string summary = $"{analysis.Target.TypeDisplayName} | symbols={analysis.StateSymbols.Members.Length} | bindings={analysis.StateChangeBindings.Members.Length} | handlers={analysis.StateChangeCommandHandlers.Members.Length}";
_ = builder.Append(" \"");
@@ -1,3 +1,10 @@
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.Models"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using Microsoft.CodeAnalysis;
using System.Collections.Immutable;
@@ -14,7 +21,8 @@ namespace StgSharp.UserInterface.Generator
string? metadataName
)
{
return IsStateSymbolAttribute(metadataName) || metadataName == StateChangeBindingAttribute;
return IsStateSymbolAttribute(metadataName) ||
metadataName == StateChangeBindingAttribute;
}
public static bool IsStateSymbolAttribute(
@@ -1,6 +1,13 @@
using System.Collections.Immutable;
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.Pipeline"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Immutable;
using System.Threading;
namespace StgSharp.UserInterface.Generator
@@ -12,12 +19,13 @@ namespace StgSharp.UserInterface.Generator
SyntaxNode node
)
{
return node is TypeDeclarationSyntax typeDeclaration && HasAttributedMembers(typeDeclaration);
return node is TypeDeclarationSyntax typeDeclaration &&
HasAttributedMembers(typeDeclaration);
}
public static PanelStateIncrementalGeneratorTypeTarget? Transform(
GeneratorSyntaxContext context,
CancellationToken cancellationToken
GeneratorSyntaxContext context,
CancellationToken cancellationToken
)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -26,14 +34,12 @@ namespace StgSharp.UserInterface.Generator
return null;
}
if (context.SemanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken) is not INamedTypeSymbol typeSymbol)
{
if (context.SemanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken) is not INamedTypeSymbol typeSymbol) {
return null;
}
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> markedMembers = CollectMarkedMembers(typeSymbol);
if (markedMembers.IsDefaultOrEmpty)
{
if (markedMembers.IsDefaultOrEmpty) {
return null;
}
@@ -43,6 +49,50 @@ namespace StgSharp.UserInterface.Generator
markedMembers);
}
private static ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> CollectMarkedMembers(
INamedTypeSymbol typeSymbol
)
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Builder builder =
ImmutableArray.CreateBuilder<PanelStateIncrementalGeneratorMarkedMember>();
foreach (ISymbol member in typeSymbol.GetMembers())
{
foreach (AttributeData attributeData in member.GetAttributes())
{
string? metadataName = attributeData.AttributeClass?.ToDisplayString();
if (!PanelStateIncrementalGeneratorKnownAttributes.IsKnown(metadataName))
{
continue;
}
builder.Add(
new PanelStateIncrementalGeneratorMarkedMember(member, metadataName!,
member.Name,
GetSymbolTypeName(member)));
break;
}
}
return builder.ToImmutable();
}
private static string GetSymbolTypeName(
ISymbol symbol
)
{
return symbol switch
{
IFieldSymbol fieldSymbol => fieldSymbol.Type
.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
IPropertySymbol propertySymbol => propertySymbol.Type
.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
IMethodSymbol methodSymbol => methodSymbol.ReturnType
.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
_ => symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
};
}
private static bool HasAttributedMembers(
TypeDeclarationSyntax typeDeclaration
)
@@ -61,48 +111,5 @@ namespace StgSharp.UserInterface.Generator
return false;
}
private static ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> CollectMarkedMembers(
INamedTypeSymbol typeSymbol
)
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Builder builder =
ImmutableArray.CreateBuilder<PanelStateIncrementalGeneratorMarkedMember>();
foreach (ISymbol member in typeSymbol.GetMembers())
{
foreach (AttributeData attributeData in member.GetAttributes())
{
string? metadataName = attributeData.AttributeClass?.ToDisplayString();
if (!PanelStateIncrementalGeneratorKnownAttributes.IsKnown(metadataName))
{
continue;
}
builder.Add(
new PanelStateIncrementalGeneratorMarkedMember(
member,
metadataName!,
member.Name,
GetSymbolTypeName(member)));
break;
}
}
return builder.ToImmutable();
}
private static string GetSymbolTypeName(
ISymbol symbol
)
{
return symbol switch
{
IFieldSymbol fieldSymbol => fieldSymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
IPropertySymbol propertySymbol => propertySymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
IMethodSymbol methodSymbol => methodSymbol.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
_ => symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
};
}
}
}
@@ -1,20 +1,30 @@
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.StateChangeBindings"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System.Collections.Immutable;
using System.Linq;
namespace StgSharp.UserInterface.Generator;
internal static class PanelStateIncrementalGeneratorStateChangeBindings
namespace StgSharp.UserInterface.Generator
{
public static StateChangeBindingPartAnalysis Analyze(
PanelStateIncrementalGeneratorTypeTarget target
)
internal static class PanelStateIncrementalGeneratorStateChangeBindings
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members = target.MarkedMembers
.Where(static member => member.AttributeMetadataName == PanelStateIncrementalGeneratorKnownAttributes.StateChangeBindingAttribute)
.ToImmutableArray();
return new StateChangeBindingPartAnalysis(
target.TypeDisplayName,
members);
public static StateChangeBindingPartAnalysis Analyze(
PanelStateIncrementalGeneratorTypeTarget target
)
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members = target.MarkedMembers
.Where(static member => member.AttributeMetadataName == PanelStateIncrementalGeneratorKnownAttributes.StateChangeBindingAttribute)
.ToImmutableArray();
return new StateChangeBindingPartAnalysis(
target.TypeDisplayName,
members);
}
}
}
@@ -1,61 +1,70 @@
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.StateCommandHandlers"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
namespace StgSharp.UserInterface.Generator;
internal static class PanelStateIncrementalGeneratorStateCommandHandlers
namespace StgSharp.UserInterface.Generator
{
public static StateChangeCommandHandlerPartAnalysis Analyze(
PanelStateIncrementalGeneratorTypeTarget target,
PanelStateSymbolPartAnalysis stateSymbols,
StateChangeBindingPartAnalysis stateChangeBindings
)
internal static class PanelStateIncrementalGeneratorStateCommandHandlers
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members = MergeMembers(
stateChangeBindings.Members,
stateSymbols.Members);
return new StateChangeCommandHandlerPartAnalysis(
target.TypeDisplayName,
members);
}
private static ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> MergeMembers(
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> primaryMembers,
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> secondaryMembers
)
{
if (primaryMembers.IsDefaultOrEmpty && secondaryMembers.IsDefaultOrEmpty)
public static StateChangeCommandHandlerPartAnalysis Analyze(
PanelStateIncrementalGeneratorTypeTarget target,
PanelStateSymbolPartAnalysis stateSymbols,
StateChangeBindingPartAnalysis stateChangeBindings
)
{
return ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Empty;
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members = MergeMembers(
stateChangeBindings.Members,
stateSymbols.Members);
return new StateChangeCommandHandlerPartAnalysis(
target.TypeDisplayName,
members);
}
HashSet<string> seen = new(StringComparer.Ordinal);
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Builder builder =
ImmutableArray.CreateBuilder<PanelStateIncrementalGeneratorMarkedMember>();
AddMembers(builder, seen, primaryMembers);
AddMembers(builder, seen, secondaryMembers);
return builder.ToImmutable();
}
private static void AddMembers(
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Builder builder,
HashSet<string> seen,
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members
)
{
foreach (PanelStateIncrementalGeneratorMarkedMember member in members)
private static void AddMembers(
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Builder builder,
HashSet<string> seen,
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members
)
{
string key = member.Symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
if (!seen.Add(key))
foreach (PanelStateIncrementalGeneratorMarkedMember member in members)
{
continue;
string key = member.Symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
if (!seen.Add(key))
{
continue;
}
builder.Add(member);
}
}
private static ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> MergeMembers(
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> primaryMembers,
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> secondaryMembers
)
{
if (primaryMembers.IsDefaultOrEmpty && secondaryMembers.IsDefaultOrEmpty) {
return ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Empty;
}
builder.Add(member);
HashSet<string> seen = new(StringComparer.Ordinal);
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember>.Builder builder =
ImmutableArray.CreateBuilder<PanelStateIncrementalGeneratorMarkedMember>();
AddMembers(builder, seen, primaryMembers);
AddMembers(builder, seen, secondaryMembers);
return builder.ToImmutable();
}
}
}
@@ -1,20 +1,30 @@
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator.StateSymbols"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System.Collections.Immutable;
using System.Linq;
namespace StgSharp.UserInterface.Generator;
internal static class PanelStateIncrementalGeneratorStateSymbols
namespace StgSharp.UserInterface.Generator
{
public static PanelStateSymbolPartAnalysis Analyze(
PanelStateIncrementalGeneratorTypeTarget target
)
internal static class PanelStateIncrementalGeneratorStateSymbols
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members = target.MarkedMembers
.Where(static member => PanelStateIncrementalGeneratorKnownAttributes.IsStateSymbolAttribute(member.AttributeMetadataName))
.ToImmutableArray();
return new PanelStateSymbolPartAnalysis(
target.TypeDisplayName,
members);
public static PanelStateSymbolPartAnalysis Analyze(
PanelStateIncrementalGeneratorTypeTarget target
)
{
ImmutableArray<PanelStateIncrementalGeneratorMarkedMember> members = target.MarkedMembers
.Where(static member => PanelStateIncrementalGeneratorKnownAttributes.IsStateSymbolAttribute(member.AttributeMetadataName))
.ToImmutableArray();
return new PanelStateSymbolPartAnalysis(
target.TypeDisplayName,
members);
}
}
}
@@ -1,37 +1,65 @@
using System.Collections.Immutable;
// -----------------------------------------------------------------------------
// file="PanelStateIncrementalGenerator"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using Microsoft.CodeAnalysis;
using System.Collections.Immutable;
namespace StgSharp.UserInterface.Generator;
[Generator(LanguageNames.CSharp)]
public sealed class PanelStateIncrementalGenerator : IIncrementalGenerator
namespace StgSharp.UserInterface.Generator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
[Generator(LanguageNames.CSharp)]
public sealed class PanelStateIncrementalGenerator : IIncrementalGenerator
{
IncrementalValuesProvider<PanelStateIncrementalGeneratorTypeTarget> typeTargets = context.SyntaxProvider
.CreateSyntaxProvider(
static (node, _) => PanelStateIncrementalGeneratorPipeline.IsCandidate(node),
static (syntaxContext, cancellationToken) =>
PanelStateIncrementalGeneratorPipeline.Transform(syntaxContext, cancellationToken))
.Where(static target => target is not null)
.Select(static (target, _) => target!);
IncrementalValueProvider<ImmutableArray<PanelStateIncrementalGeneratorTypeTarget>> collectedTypeTargets = typeTargets.Collect();
public void Initialize(
IncrementalGeneratorInitializationContext context
)
{
IncrementalValuesProvider<PanelStateIncrementalGeneratorTypeTarget> typeTargets = context.SyntaxProvider
.CreateSyntaxProvider(
static(
node,
_
) => PanelStateIncrementalGeneratorPipeline.IsCandidate(node),
static(
syntaxContext,
cancellationToken
) => PanelStateIncrementalGeneratorPipeline.Transform(syntaxContext, cancellationToken))
.Where(static target => target is not null)
.Select(static(
target,
_
) => target!);
IncrementalValueProvider<PanelStateIncrementalGeneratorInput> generatorInput = context.CompilationProvider
.Combine(collectedTypeTargets)
.Select(
static (pair, _) => new PanelStateIncrementalGeneratorInput(
pair.Left,
pair.Right));
IncrementalValueProvider<ImmutableArray<PanelStateIncrementalGeneratorTypeTarget>> collectedTypeTargets = typeTargets.Collect();
IncrementalValueProvider<PanelStateIncrementalGeneratorOutput> generatorOutput = generatorInput
.Select(
static (input, _) => PanelStateIncrementalGeneratorAnalysis.Analyze(input));
IncrementalValueProvider<PanelStateIncrementalGeneratorInput> generatorInput = context.CompilationProvider
.Combine(collectedTypeTargets)
.Select(
static(
pair,
_
) => new PanelStateIncrementalGeneratorInput(
pair.Left,
pair.Right));
IncrementalValueProvider<PanelStateIncrementalGeneratorOutput> generatorOutput = generatorInput
.Select(
static(
input,
_
) => PanelStateIncrementalGeneratorAnalysis.Analyze(input));
context.RegisterSourceOutput(
generatorOutput,
static(
productionContext,
source
) => PanelStateIncrementalGeneratorEmitter.Emit(productionContext, source));
}
context.RegisterSourceOutput(
generatorOutput,
static (productionContext, source) =>
PanelStateIncrementalGeneratorEmitter.Emit(productionContext, source));
}
}
+6
View File
@@ -1,3 +1,9 @@
// -----------------------------------------------------------------------------
// file="Global"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
global using System;
global using System.Collections.Generic;
@@ -1,33 +1,25 @@
// -----------------------------------------------------------------------------
// file="PanelStateSample"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using System;
namespace StgSharp.UserInterface.Sample
{
public sealed class PanelStateSample : PanelState
{
public const string SampleStatePath = nameof(PanelStateSample) + "." + nameof(SampleState);
private int sampleState;
public PanelStateSample()
: base(nameof(PanelStateSample))
{
}
public PanelStateSample() : base(nameof(PanelStateSample)) { }
public int SampleState => sampleState;
// 生成器拆分后,这里相当于某个节点 handler 的 guard,
// 对应 ICommand 语义中的 CanExecute。
private static bool CanApplySampleStateChange(
int origin,
int current,
StateValueCommand<int> command
)
{
return string.Equals(command.StatePath, SampleStatePath, StringComparison.Ordinal)
&& current >= 0
&& origin != current;
}
// 实际项目里这整个 StateChangeHandler 都由源生成器产出;
// 这里手写展开,只是为了展示“没有生成器时 VSS 代码长什么样”。
public void ApplySampleStateChangeCommand(
@@ -38,8 +30,7 @@ namespace StgSharp.UserInterface.Sample
int origin = sampleState;
int current = command.Value;
if (!CanApplySampleStateChange(origin, current, command))
{
if (!CanApplySampleStateChange(origin, current, command)) {
return;
}
@@ -50,8 +41,8 @@ namespace StgSharp.UserInterface.Sample
// 生成器拆分后,这里相当于某个节点写入后的 post-change hook,
// 对应手写体系里常见的 OnChange 位置。
private static void BroadcastSampleStateChanged(
int origin,
int current
int origin,
int current
)
{
_ = origin;
@@ -61,5 +52,18 @@ namespace StgSharp.UserInterface.Sample
// 这里只能继续手写内部同步/广播逻辑;正式版本由生成器织入。
}
// 生成器拆分后,这里相当于某个节点 handler 的 guard,
// 对应 ICommand 语义中的 CanExecute。
private static bool CanApplySampleStateChange(
int origin,
int current,
StateValueCommand<int> command
)
{
return string.Equals(command.StatePath, SampleStatePath, StringComparison.Ordinal) &&
current >= 0 &&
origin != current;
}
}
}