mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-31 18:39:00 +08:00
feat(generator): 添加 BindNodeSignal 和 GetNode 源代码生成器
- 实现 BindNodeSignalGenerator 用于生成节点信号绑定与解绑逻辑 - 实现 GetNodeGenerator 用于生成 Godot 节点获取注入逻辑 - 添加 BindNodeSignalDiagnostics 提供详细的诊断错误信息 - 集成到 AnalyzerReleases.Unshipped.md 追踪新的分析规则 - 支持 [BindNodeSignal] 属性的方法自动生成事件绑定代码 - 支持 [GetNode] 属性的字段自动生成节点获取代码 - 提供生命周期方法集成的智能提示和验证功能
This commit is contained in:
parent
2dfd6e044f
commit
6fa4580893
@ -526,11 +526,11 @@ public class BindNodeSignalGeneratorTests
|
|||||||
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
|
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
|
||||||
};
|
};
|
||||||
|
|
||||||
test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_Godot_BindNodeSignal_011", DiagnosticSeverity.Error)
|
test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_Common_Class_002", DiagnosticSeverity.Error)
|
||||||
.WithLocation(0)
|
.WithLocation(0)
|
||||||
.WithArguments("Hud", "__BindNodeSignals_Generated"));
|
.WithArguments("Hud", "__BindNodeSignals_Generated"));
|
||||||
|
|
||||||
test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_Godot_BindNodeSignal_011", DiagnosticSeverity.Error)
|
test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_Common_Class_002", DiagnosticSeverity.Error)
|
||||||
.WithLocation(1)
|
.WithLocation(1)
|
||||||
.WithArguments("Hud", "__UnbindNodeSignals_Generated"));
|
.WithArguments("Hud", "__UnbindNodeSignals_Generated"));
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,4 @@
|
|||||||
using GFramework.Godot.SourceGenerators.Tests.Core;
|
using GFramework.Godot.SourceGenerators.Tests.Core;
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp.Testing;
|
|
||||||
using Microsoft.CodeAnalysis.Testing;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace GFramework.Godot.SourceGenerators.Tests.GetNode;
|
namespace GFramework.Godot.SourceGenerators.Tests.GetNode;
|
||||||
|
|
||||||
@ -240,4 +236,71 @@ public class GetNodeGeneratorTests
|
|||||||
|
|
||||||
await test.RunAsync();
|
await test.RunAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Reports_Diagnostic_When_Generated_Injection_Method_Name_Already_Exists()
|
||||||
|
{
|
||||||
|
const string source = """
|
||||||
|
using System;
|
||||||
|
using GFramework.Godot.SourceGenerators.Abstractions;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace GFramework.Godot.SourceGenerators.Abstractions
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
|
||||||
|
public sealed class GetNodeAttribute : Attribute
|
||||||
|
{
|
||||||
|
public GetNodeAttribute() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NodeLookupMode
|
||||||
|
{
|
||||||
|
Auto = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Godot
|
||||||
|
{
|
||||||
|
public class Node
|
||||||
|
{
|
||||||
|
public virtual void _Ready() {}
|
||||||
|
public T GetNode<T>(string path) where T : Node => throw new InvalidOperationException(path);
|
||||||
|
public T? GetNodeOrNull<T>(string path) where T : Node => default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HBoxContainer : Node
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace TestApp
|
||||||
|
{
|
||||||
|
public partial class TopBar : HBoxContainer
|
||||||
|
{
|
||||||
|
[GetNode]
|
||||||
|
private HBoxContainer _leftContainer = null!;
|
||||||
|
|
||||||
|
private void {|#0:__InjectGetNodes_Generated|}()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
var test = new CSharpSourceGeneratorTest<GetNodeGenerator, DefaultVerifier>
|
||||||
|
{
|
||||||
|
TestState =
|
||||||
|
{
|
||||||
|
Sources = { source }
|
||||||
|
},
|
||||||
|
DisabledDiagnostics = { "GF_Common_Trace_001" },
|
||||||
|
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
|
||||||
|
};
|
||||||
|
|
||||||
|
test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_Common_Class_002", DiagnosticSeverity.Error)
|
||||||
|
.WithLocation(0)
|
||||||
|
.WithArguments("TopBar", "__InjectGetNodes_Generated"));
|
||||||
|
|
||||||
|
await test.RunAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -21,4 +21,3 @@
|
|||||||
GF_Godot_BindNodeSignal_008 | GFramework.Godot | Warning | BindNodeSignalDiagnostics
|
GF_Godot_BindNodeSignal_008 | GFramework.Godot | Warning | BindNodeSignalDiagnostics
|
||||||
GF_Godot_BindNodeSignal_009 | GFramework.Godot | Warning | BindNodeSignalDiagnostics
|
GF_Godot_BindNodeSignal_009 | GFramework.Godot | Warning | BindNodeSignalDiagnostics
|
||||||
GF_Godot_BindNodeSignal_010 | GFramework.Godot | Error | BindNodeSignalDiagnostics
|
GF_Godot_BindNodeSignal_010 | GFramework.Godot | Error | BindNodeSignalDiagnostics
|
||||||
GF_Godot_BindNodeSignal_011 | GFramework.Godot | Error | BindNodeSignalDiagnostics
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using GFramework.Godot.SourceGenerators.Diagnostics;
|
using GFramework.Godot.SourceGenerators.Diagnostics;
|
||||||
using GFramework.SourceGenerators.Common.Constants;
|
using GFramework.SourceGenerators.Common.Constants;
|
||||||
using GFramework.SourceGenerators.Common.Diagnostics;
|
using GFramework.SourceGenerators.Common.Diagnostics;
|
||||||
@ -88,7 +89,11 @@ public sealed class BindNodeSignalGenerator : IIncrementalGenerator
|
|||||||
if (!CanGenerateForType(context, group, typeSymbol))
|
if (!CanGenerateForType(context, group, typeSymbol))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (HasGeneratedMethodNameConflict(context, group, typeSymbol))
|
if (typeSymbol.ReportGeneratedMethodConflicts(
|
||||||
|
context,
|
||||||
|
group.Methods[0].Method.Identifier.GetLocation(),
|
||||||
|
BindMethodName,
|
||||||
|
UnbindMethodName))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var bindings = new List<SignalBindingInfo>();
|
var bindings = new List<SignalBindingInfo>();
|
||||||
@ -390,36 +395,6 @@ public sealed class BindNodeSignalGenerator : IIncrementalGenerator
|
|||||||
typeSymbol.Name));
|
typeSymbol.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasGeneratedMethodNameConflict(
|
|
||||||
SourceProductionContext context,
|
|
||||||
TypeGroup group,
|
|
||||||
INamedTypeSymbol typeSymbol)
|
|
||||||
{
|
|
||||||
var hasConflict = false;
|
|
||||||
|
|
||||||
foreach (var generatedMethodName in new[] { BindMethodName, UnbindMethodName })
|
|
||||||
{
|
|
||||||
var conflictingMethod = typeSymbol.GetMembers()
|
|
||||||
.OfType<IMethodSymbol>()
|
|
||||||
.FirstOrDefault(method =>
|
|
||||||
method.Name == generatedMethodName &&
|
|
||||||
method.Parameters.Length == 0 &&
|
|
||||||
method.TypeParameters.Length == 0);
|
|
||||||
|
|
||||||
if (conflictingMethod is null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
context.ReportDiagnostic(Diagnostic.Create(
|
|
||||||
BindNodeSignalDiagnostics.GeneratedMethodNameConflict,
|
|
||||||
conflictingMethod.Locations.FirstOrDefault() ?? group.Methods[0].Method.Identifier.GetLocation(),
|
|
||||||
typeSymbol.Name,
|
|
||||||
generatedMethodName));
|
|
||||||
hasConflict = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasConflict;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IMethodSymbol? FindLifecycleMethod(
|
private static IMethodSymbol? FindLifecycleMethod(
|
||||||
INamedTypeSymbol typeSymbol,
|
INamedTypeSymbol typeSymbol,
|
||||||
string methodName)
|
string methodName)
|
||||||
@ -627,7 +602,7 @@ public sealed class BindNodeSignalGenerator : IIncrementalGenerator
|
|||||||
|
|
||||||
public int GetHashCode(MethodCandidate obj)
|
public int GetHashCode(MethodCandidate obj)
|
||||||
{
|
{
|
||||||
return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
|
return RuntimeHelpers.GetHashCode(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,16 +126,4 @@ public static class BindNodeSignalDiagnostics
|
|||||||
PathContests.GodotNamespace,
|
PathContests.GodotNamespace,
|
||||||
DiagnosticSeverity.Error,
|
DiagnosticSeverity.Error,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用户代码中已存在与生成方法同名的成员。
|
|
||||||
/// </summary>
|
|
||||||
public static readonly DiagnosticDescriptor GeneratedMethodNameConflict =
|
|
||||||
new(
|
|
||||||
"GF_Godot_BindNodeSignal_011",
|
|
||||||
"Generated method name conflicts with an existing member",
|
|
||||||
"Class '{0}' already defines method '{1}()', which conflicts with [BindNodeSignal] generated code",
|
|
||||||
PathContests.GodotNamespace,
|
|
||||||
DiagnosticSeverity.Error,
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
@ -1,12 +1,6 @@
|
|||||||
using System.Collections.Immutable;
|
|
||||||
using System.Text;
|
|
||||||
using GFramework.Godot.SourceGenerators.Diagnostics;
|
using GFramework.Godot.SourceGenerators.Diagnostics;
|
||||||
using GFramework.SourceGenerators.Common.Constants;
|
using GFramework.SourceGenerators.Common.Constants;
|
||||||
using GFramework.SourceGenerators.Common.Diagnostics;
|
using GFramework.SourceGenerators.Common.Diagnostics;
|
||||||
using GFramework.SourceGenerators.Common.Extensions;
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
||||||
|
|
||||||
namespace GFramework.Godot.SourceGenerators;
|
namespace GFramework.Godot.SourceGenerators;
|
||||||
|
|
||||||
@ -95,6 +89,12 @@ public sealed class GetNodeGenerator : IIncrementalGenerator
|
|||||||
if (!CanGenerateForType(context, group, typeSymbol))
|
if (!CanGenerateForType(context, group, typeSymbol))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (typeSymbol.ReportGeneratedMethodConflicts(
|
||||||
|
context,
|
||||||
|
group.Fields[0].Variable.Identifier.GetLocation(),
|
||||||
|
InjectionMethodName))
|
||||||
|
continue;
|
||||||
|
|
||||||
var bindings = new List<NodeBindingInfo>();
|
var bindings = new List<NodeBindingInfo>();
|
||||||
|
|
||||||
foreach (var candidate in group.Fields)
|
foreach (var candidate in group.Fields)
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
; Unshipped analyzer release
|
; Unshipped analyzer release
|
||||||
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
|
; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
|
||||||
|
|
||||||
### New Rules
|
### New Rules
|
||||||
|
|
||||||
Rule ID | Category | Severity | Notes
|
Rule ID | Category | Severity | Notes
|
||||||
---------------------|-------------------|----------|-------------------
|
---------------------|-------------------|----------|-------------------
|
||||||
GF_Common_Class_001 | GFramework.Common | Error | CommonDiagnostics
|
GF_Common_Class_001 | GFramework.Common | Error | CommonDiagnostics
|
||||||
GF_Common_Trace_001 | GFramework.Trace | Info | CommonDiagnostics
|
GF_Common_Class_002 | GFramework.Common | Error | CommonDiagnostics
|
||||||
|
GF_Common_Trace_001 | GFramework.Trace | Info | CommonDiagnostics
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using Microsoft.CodeAnalysis;
|
namespace GFramework.SourceGenerators.Common.Diagnostics;
|
||||||
|
|
||||||
namespace GFramework.SourceGenerators.Common.Diagnostics;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提供通用诊断描述符的静态类
|
/// 提供通用诊断描述符的静态类
|
||||||
@ -27,6 +25,23 @@ public static class CommonDiagnostics
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定义生成方法名与用户代码冲突的诊断描述符。
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 该诊断用于保护生成器保留的方法名,避免用户代码手动声明了相同零参数方法时出现重复成员错误,
|
||||||
|
/// 并使多个生成器可以复用同一条一致的冲突报告规则。
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly DiagnosticDescriptor GeneratedMethodNameConflict =
|
||||||
|
new(
|
||||||
|
"GF_Common_Class_002",
|
||||||
|
"Generated method name conflicts with an existing member",
|
||||||
|
"Class '{0}' already defines method '{1}()', which conflicts with generated code",
|
||||||
|
"GFramework.Common",
|
||||||
|
DiagnosticSeverity.Error,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义源代码生成器跟踪信息的诊断描述符
|
/// 定义源代码生成器跟踪信息的诊断描述符
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
using GFramework.SourceGenerators.Common.Diagnostics;
|
||||||
|
|
||||||
|
namespace GFramework.SourceGenerators.Common.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提供生成方法名冲突校验的通用扩展。
|
||||||
|
/// </summary>
|
||||||
|
public static class GeneratedMethodConflictExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 检查目标类型上是否已存在与生成器保留方法同名的零参数方法,并在冲突时报告统一诊断。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="typeSymbol">待校验的目标类型。</param>
|
||||||
|
/// <param name="context">源代码生成上下文。</param>
|
||||||
|
/// <param name="fallbackLocation">当冲突成员缺少源码位置时使用的后备位置。</param>
|
||||||
|
/// <param name="generatedMethodNames">生成器将保留的零参数方法名集合。</param>
|
||||||
|
/// <returns>若发现任一冲突则返回 <c>true</c>。</returns>
|
||||||
|
public static bool ReportGeneratedMethodConflicts(
|
||||||
|
this INamedTypeSymbol typeSymbol,
|
||||||
|
SourceProductionContext context,
|
||||||
|
Location fallbackLocation,
|
||||||
|
params string[] generatedMethodNames)
|
||||||
|
{
|
||||||
|
var hasConflict = false;
|
||||||
|
|
||||||
|
foreach (var generatedMethodName in generatedMethodNames.Distinct(StringComparer.Ordinal))
|
||||||
|
{
|
||||||
|
var conflictingMethod = typeSymbol.GetMembers()
|
||||||
|
.OfType<IMethodSymbol>()
|
||||||
|
.FirstOrDefault(method =>
|
||||||
|
!method.IsImplicitlyDeclared &&
|
||||||
|
string.Equals(method.Name, generatedMethodName, StringComparison.Ordinal) &&
|
||||||
|
method.Parameters.Length == 0 &&
|
||||||
|
method.TypeParameters.Length == 0);
|
||||||
|
|
||||||
|
if (conflictingMethod is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
|
CommonDiagnostics.GeneratedMethodNameConflict,
|
||||||
|
conflictingMethod.Locations.FirstOrDefault() ?? fallbackLocation,
|
||||||
|
typeSymbol.Name,
|
||||||
|
generatedMethodName));
|
||||||
|
hasConflict = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasConflict;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -377,6 +377,84 @@ public class ContextGetGeneratorTests
|
|||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Reports_Diagnostic_When_Generated_Injection_Method_Name_Already_Exists()
|
||||||
|
{
|
||||||
|
var source = """
|
||||||
|
using System;
|
||||||
|
using GFramework.SourceGenerators.Abstractions.Rule;
|
||||||
|
|
||||||
|
namespace GFramework.SourceGenerators.Abstractions.Rule
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||||
|
public sealed class ContextAwareAttribute : Attribute { }
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Field, Inherited = false)]
|
||||||
|
public sealed class GetModelAttribute : Attribute { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Rule
|
||||||
|
{
|
||||||
|
public interface IContextAware { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Model
|
||||||
|
{
|
||||||
|
public interface IModel { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Systems
|
||||||
|
{
|
||||||
|
public interface ISystem { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Utility
|
||||||
|
{
|
||||||
|
public interface IUtility { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class ContextAwareServiceExtensions
|
||||||
|
{
|
||||||
|
public static T GetModel<T>(this object contextAware) => default!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace TestApp
|
||||||
|
{
|
||||||
|
public interface IInventoryModel : GFramework.Core.Abstractions.Model.IModel { }
|
||||||
|
|
||||||
|
[ContextAware]
|
||||||
|
public partial class InventoryPanel
|
||||||
|
{
|
||||||
|
[GetModel]
|
||||||
|
private IInventoryModel _model = null!;
|
||||||
|
|
||||||
|
private void {|#0:__InjectContextBindings_Generated|}()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
var test = new CSharpSourceGeneratorTest<ContextGetGenerator, DefaultVerifier>
|
||||||
|
{
|
||||||
|
TestState =
|
||||||
|
{
|
||||||
|
Sources = { source }
|
||||||
|
},
|
||||||
|
DisabledDiagnostics = { "GF_Common_Trace_001" },
|
||||||
|
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
|
||||||
|
};
|
||||||
|
|
||||||
|
test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_Common_Class_002", DiagnosticSeverity.Error)
|
||||||
|
.WithLocation(0)
|
||||||
|
.WithArguments("InventoryPanel", "__InjectContextBindings_Generated"));
|
||||||
|
|
||||||
|
await test.RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Ignores_NonInferable_Const_Field_For_GetAll_Class_Without_Diagnostic()
|
public async Task Ignores_NonInferable_Const_Field_For_GetAll_Class_Without_Diagnostic()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Text;
|
|
||||||
using GFramework.SourceGenerators.Common.Constants;
|
using GFramework.SourceGenerators.Common.Constants;
|
||||||
using GFramework.SourceGenerators.Common.Diagnostics;
|
using GFramework.SourceGenerators.Common.Diagnostics;
|
||||||
using GFramework.SourceGenerators.Common.Extensions;
|
|
||||||
using GFramework.SourceGenerators.Common.Info;
|
using GFramework.SourceGenerators.Common.Info;
|
||||||
using GFramework.SourceGenerators.Diagnostics;
|
using GFramework.SourceGenerators.Diagnostics;
|
||||||
|
|
||||||
@ -220,6 +218,12 @@ public sealed class ContextGetGenerator : IIncrementalGenerator
|
|||||||
if (!CanGenerateForType(context, workItem, symbols))
|
if (!CanGenerateForType(context, workItem, symbols))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (workItem.TypeSymbol.ReportGeneratedMethodConflicts(
|
||||||
|
context,
|
||||||
|
GetTypeLocation(workItem),
|
||||||
|
InjectionMethodName))
|
||||||
|
continue;
|
||||||
|
|
||||||
var bindings = CollectBindings(context, workItem, descriptors, symbols);
|
var bindings = CollectBindings(context, workItem, descriptors, symbols);
|
||||||
if (bindings.Count == 0 && workItem.GetAllDeclaration is null)
|
if (bindings.Count == 0 && workItem.GetAllDeclaration is null)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user