Skip to content

Commit

Permalink
Fix null ref in complex per resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Sep 22, 2023
1 parent cce403a commit e826370
Show file tree
Hide file tree
Showing 16 changed files with 50 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/ApiInvocationProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core;

using System.Text.RegularExpressions;
Expand Down
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Cache.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ReSharper disable HeapView.ObjectAllocation.Evident
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core;

using System.Collections.Concurrent;
Expand Down
3 changes: 1 addition & 2 deletions src/Pure.DI.Core/Core/Code/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ namespace Pure.DI.Core.Code;

internal record Block(
IStatement? Parent,
LinkedList<IStatement> Statements,
HashSet<MdBinding> Created) : IStatement
LinkedList<IStatement> Statements) : IStatement
{
public Variable Current => Statements.OfType<Variable>().Last();
}
24 changes: 13 additions & 11 deletions src/Pure.DI.Core/Core/Code/BlockCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
namespace Pure.DI.Core.Code;
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class BlockCodeBuilder: ICodeBuilder<Block>
{
public void Build(BuildContext ctx, in Block block)
{
var variable = ctx.Variable;
if (!TryCreate(variable))
if (!TryCreate(ctx, variable))
{
return;
}

ctx.Code.AppendLine($"// Level {variable.Info.Level}");
var toCheckExistence = variable.Node.Lifetime != Lifetime.Transient;
var level = ctx.Level;
if (toCheckExistence)
{
var checkExpression = variable.InstanceType.IsValueType switch
Expand All @@ -32,11 +35,12 @@ public void Build(BuildContext ctx, in Block block)
ctx.Code.AppendLine($"if ({checkExpression})");
ctx.Code.AppendLine("{");
ctx.Code.IncIndent();
level++;
}

foreach (var statement in block.Statements)
{
ctx.StatementBuilder.Build(ctx with{ Variable = statement.Current }, statement);
ctx.StatementBuilder.Build(ctx with { Level = level, Variable = statement.Current }, statement);
}

if (!toCheckExistence)
Expand Down Expand Up @@ -69,22 +73,20 @@ public void Build(BuildContext ctx, in Block block)
ctx.Code.AppendLine();
}

private static bool TryCreate(Variable variable)
private static bool TryCreate(BuildContext ctx, Variable variable)
{
// A transient instance must be created each time
if (variable.Node.Lifetime == Lifetime.Transient)
{
return true;
}

// An instance has been created in some parent block
if (variable.GetPath().OfType<Block>().Any(i => i.Created.Contains(variable.Node.Binding)))
if (ctx.Level >= variable.Info.Level)
{
return false;
}

// An instance has already been created in the current block
var block = variable.GetPath().OfType<Block>().First();
return block.Created.Add(variable.Node.Binding);

variable.Info.Level = ctx.Level;
return true;
}
}
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Code/BuildContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Pure.DI.Core.Code;

internal record BuildContext(
int Level,
IBuildTools BuildTools,
ICodeBuilder<IStatement> StatementBuilder,
DependencyGraph DependencyGraph,
Expand Down
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Code/BuildTools.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ReSharper disable InvertIf
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class BuildTools : IBuildTools
Expand Down
3 changes: 2 additions & 1 deletion src/Pure.DI.Core/Core/Code/CompositionBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ReSharper disable InvertIf
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class CompositionBuilder: IBuilder<DependencyGraph, CompositionCode>
Expand Down Expand Up @@ -33,7 +34,7 @@ public CompositionCode Build(DependencyGraph graph)
{
_cancellationToken.ThrowIfCancellationRequested();
var rootBlock = _variablesBuilder.Build(graph.Graph, map, root.Node, root.Injection);
var ctx = new BuildContext(_buildTools, _statementBuilder, graph, rootBlock.Current, new LinesBuilder(), default, isThreadSafe);
var ctx = new BuildContext(0, _buildTools, _statementBuilder, graph, rootBlock.Current, new LinesBuilder(), default, isThreadSafe);
foreach (var perResolveVar in map.GetPerResolves())
{
ctx.Code.AppendLine($"{perResolveVar.InstanceType} {perResolveVar.VarName} = default({perResolveVar.InstanceType});");
Expand Down
4 changes: 3 additions & 1 deletion src/Pure.DI.Core/Core/Code/ConstructCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class ConstructCodeBuilder : ICodeBuilder<DpConstruct>
Expand Down Expand Up @@ -35,6 +36,7 @@ private static void BuildEnumerable(BuildContext ctx)
{
var variable = ctx.Variable;
var code = ctx.Code;
var level = ctx.Level + 1;
var localFuncName = $"LocalFunc_{variable.VarName}";
code.AppendLine($"{variable.InstanceType} {localFuncName}()");
code.AppendLine("{");
Expand All @@ -43,7 +45,7 @@ private static void BuildEnumerable(BuildContext ctx)
var hasYieldReturn = false;
foreach (var statement in variable.Args)
{
ctx.StatementBuilder.Build(ctx with { Variable = statement.Current }, statement);
ctx.StatementBuilder.Build(ctx with { Level = level, Variable = statement.Current }, statement);
code.AppendLine($"yield return {ctx.BuildTools.OnInjected(ctx, statement.Current)};");
hasYieldReturn = true;
}
Expand Down
11 changes: 9 additions & 2 deletions src/Pure.DI.Core/Core/Code/FactoryCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace Pure.DI.Core.Code;
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class FactoryCodeBuilder: ICodeBuilder<DpFactory>
{
Expand All @@ -8,6 +9,12 @@ public void Build(BuildContext ctx, in DpFactory factory)
{
var variable = ctx.Variable;
var code = ctx.Code;
var level = ctx.Level;
if (variable.Node.IsLazy())
{
level++;
}

// Rewrites syntax tree
var finishLabel = $"label{Names.Salt}{variable.Id}";
var injections = new List<FactoryRewriter.Injection>();
Expand Down Expand Up @@ -43,7 +50,7 @@ public void Build(BuildContext ctx, in DpFactory factory)
var (injection, argument) = resolvers.Current;
using (code.Indent(indent.Value))
{
ctx.StatementBuilder.Build(ctx with { Variable = argument.Current }, argument);
ctx.StatementBuilder.Build(ctx with { Level = level, Variable = argument.Current }, argument);
code.AppendLine($"{(injection.DeclarationRequired ? "var " : "")}{injection.VariableName} = {ctx.BuildTools.OnInjected(ctx, argument.Current)};");
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Pure.DI.Core/Core/Code/ImplementationCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace Pure.DI.Core.Code;
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class ImplementationCodeBuilder: ICodeBuilder<DpImplementation>
{
Expand Down
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Code/StatementCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ReSharper disable RedundantJumpStatement
// ReSharper disable InvertIf
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class StatementCodeBuilder : ICodeBuilder<IStatement>
Expand Down
4 changes: 3 additions & 1 deletion src/Pure.DI.Core/Core/Code/Variable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ internal record Variable(
int Id,
in DependencyNode Node,
in Injection Injection,
ICollection<IStatement> Args)
ICollection<IStatement> Args,
VariableInfo Info)
: IStatement
{
public Variable Current => this;
Expand Down Expand Up @@ -50,5 +51,6 @@ public string VarName
public void Reset()
{
IsCreated = false;
Info.Level = int.MaxValue;
}
}
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Code/VariableCodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ReSharper disable InvertIf
// ReSharper disable RedundantJumpStatement
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class VariableCodeBuilder : DependenciesWalker<BuildContext>, ICodeBuilder<Variable>
Expand Down
6 changes: 6 additions & 0 deletions src/Pure.DI.Core/Core/Code/VariableInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Pure.DI.Core.Code;

internal class VariableInfo
{
public int Level = int.MaxValue;
}
7 changes: 4 additions & 3 deletions src/Pure.DI.Core/Core/Code/VariablesBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core.Code;

internal class VariablesBuilder : IVariablesBuilder
Expand All @@ -11,7 +12,7 @@ public Block Build(
DependencyNode rootNode,
Injection rootInjection)
{
var rootBlock = new Block(default, new LinkedList<IStatement>(), new HashSet<MdBinding>());
var rootBlock = new Block(default, new LinkedList<IStatement>());
var rootVar = CreateVariable(rootBlock, map, rootNode, rootInjection);
rootBlock.Statements.AddFirst(rootVar);
var blocks = new Stack<Block>();
Expand Down Expand Up @@ -65,7 +66,7 @@ public Block Build(
var isBlock = depNode.Lifetime != Lifetime.Transient || variable.Node.IsLazy();
if (isBlock)
{
var depBlock = new Block(currentStatement, new LinkedList<IStatement>(), new HashSet<MdBinding>());
var depBlock = new Block(currentStatement, new LinkedList<IStatement>());
depBlock.Statements.AddFirst(depVariable);
if (!isAlreadyCreated)
{
Expand Down Expand Up @@ -125,7 +126,7 @@ private Variable CreateVariable(
}

var id = GetId(node);
var var = new Variable(parent, id, node, injection, new List<IStatement>());
var var = new Variable(parent, id, node, injection, new List<IStatement>(), new VariableInfo());
if (isSharedVar)
{
map.Add(node.Binding, var);
Expand Down
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/TypeConstructor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ReSharper disable InvertIf
// ReSharper disable once ClassNeverInstantiated.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace Pure.DI.Core;

[SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1024:Symbols should be compared for equality")]
Expand Down

0 comments on commit e826370

Please sign in to comment.