Skip to content
Merged
Prev Previous commit
Next Next commit
Improve analysis performance
  • Loading branch information
JamesNK authored and github-actions committed Mar 26, 2024
commit 58e28bf4ec79befae7befe6596be052fc6126530
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,46 @@ private RouteUsageCache(Compilation compilation)
}

public RouteUsageModel? Get(SyntaxToken syntaxToken, CancellationToken cancellationToken)
{
LastInspectedStringNode? lastInspectedStringNode = null;
return Get(syntaxToken, ref lastInspectedStringNode, cancellationToken);
}

public RouteUsageModel? Get(SyntaxToken syntaxToken, ref LastInspectedStringNode? lastInspectedStringNode, CancellationToken cancellationToken)
{
if (_lazyRoutePatterns.TryGetValue(syntaxToken, out var routeUsageModel))
{
return routeUsageModel;
}

return GetAndCache(syntaxToken, cancellationToken);
return GetAndCache(syntaxToken, ref lastInspectedStringNode, cancellationToken);
}

private RouteUsageModel? GetAndCache(SyntaxToken syntaxToken, CancellationToken cancellationToken)
private sealed class RouteUsageModelLoader
{
return _lazyRoutePatterns.GetOrAdd(syntaxToken, token =>
private readonly Compilation _compilation;
private readonly CancellationToken _cancellationToken;
private LastInspectedStringNode? _lastInspectedStringNode;

public LastInspectedStringNode? LastInspectedStringNode => _lastInspectedStringNode;

public RouteUsageModelLoader(Compilation compilation, LastInspectedStringNode? lastInspectedStringNode, CancellationToken cancellationToken)
{
if (syntaxToken.SyntaxTree == null)
_compilation = compilation;
_lastInspectedStringNode = lastInspectedStringNode;
_cancellationToken = cancellationToken;
}

public RouteUsageModel? Load(SyntaxToken token)
{
if (token.SyntaxTree == null)
{
return null;
}

var semanticModel = _compilation.GetSemanticModel(syntaxToken.SyntaxTree);
var semanticModel = _compilation.GetSemanticModel(token.SyntaxTree);

LastInspectedStringNode? lastInspectedStringNode = null;
if (!RouteStringSyntaxDetector.IsRouteStringSyntaxToken(token, semanticModel, ref lastInspectedStringNode, cancellationToken, out var options))
if (!RouteStringSyntaxDetector.IsRouteStringSyntaxToken(token, semanticModel, ref _lastInspectedStringNode, _cancellationToken, out var options))
{
return null;
}
Expand All @@ -60,10 +78,9 @@ private RouteUsageCache(Compilation compilation)
token,
semanticModel,
wellKnownTypes,
cancellationToken);
_cancellationToken);

var virtualChars = CSharpVirtualCharService.Instance.TryConvertToVirtualChars(token);
var isMvc = usageContext.UsageType == RouteUsageType.MvcAction || usageContext.UsageType == RouteUsageType.MvcController;
var tree = RoutePatternParser.TryParse(virtualChars, usageContext.RoutePatternOptions);
if (tree == null)
{
Expand All @@ -75,6 +92,15 @@ private RouteUsageCache(Compilation compilation)
RoutePattern = tree,
UsageContext = usageContext
};
});
}
}

private RouteUsageModel? GetAndCache(SyntaxToken syntaxToken, ref LastInspectedStringNode? lastInspectedStringNode, CancellationToken cancellationToken)
{
var routeUsageModelLoader = new RouteUsageModelLoader(_compilation, lastInspectedStringNode, cancellationToken);
var model = _lazyRoutePatterns.GetOrAdd(syntaxToken, routeUsageModelLoader.Load);
lastInspectedStringNode = routeUsageModelLoader.LastInspectedStringNode;

return model;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private static void AnalyzeToken(SemanticModelAnalysisContext context, RouteUsag
return;
}

var routeUsage = routeUsageCache.Get(token, cancellationToken);
var routeUsage = routeUsageCache.Get(token, ref lastInspectedStringNode, cancellationToken);
if (routeUsage is null)
{
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ static void Main() { }
// lang=Route
static readonly string _s =
""");
for (var i = 0; i < 100; i++)
for (var i = 0; i < 2000; i++)
{
builder.AppendLine(" \"a{}bc\" +");
}
Expand All @@ -588,6 +588,6 @@ static void Main() { }
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);

// Assert
Assert.Equal(100, diagnostics.Length);
Assert.Equal(2000, diagnostics.Length);
}
}