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

Include imported variables in max variables check #15956

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,30 @@ public void TooManyVariables(int i, int j, string pattern, string[] expectedMess
{
CompileAndTest(GenerateText(i, j, pattern), MaxNumberVariablesRule.Code, DiagnosticLevel.Error, expectedMessages);
}

[TestMethod]
public void TooManyVariablesAfterImport()
{
var withoutImport = GenerateText(1, MaxNumberVariablesRule.MaxNumber, "var v% = %");
CompileAndTest(withoutImport, MaxNumberVariablesRule.Code, DiagnosticLevel.Off, []);

var importTarget = """
@export()
var imported1 = 1
""";
CompileAndTest(
string.Join('\n', "import {imported1} from 'imported.bicep'", withoutImport),
MaxNumberVariablesRule.Code,
DiagnosticLevel.Error,
[$"Too many variables. Number of variables is limited to {MaxNumberVariablesRule.MaxNumber}."],
new(AdditionalFiles: [ ("imported.bicep", importTarget) ]));

CompileAndTest(
string.Join('\n', "import * as imported from 'imported.bicep'", withoutImport),
MaxNumberVariablesRule.Code,
DiagnosticLevel.Error,
[$"Too many variables. Number of variables is limited to {MaxNumberVariablesRule.MaxNumber}."],
new(AdditionalFiles: [("imported.bicep", importTarget)]));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ public override string FormatMessage(params object[] values)

override public IEnumerable<IDiagnostic> AnalyzeInternal(SemanticModel model, DiagnosticLevel diagnosticLevel)
{
if (model.Root.VariableDeclarations.Count() > MaxNumber)
var variablesInCompiledTemplate = model.Root.VariableDeclarations.Count() +
model.ImportClosureInfo.ImportedVariablesInClosure.Count();
if (variablesInCompiledTemplate > MaxNumber)
{
var firstItem = model.Root.VariableDeclarations.First();
return new IDiagnostic[] { CreateDiagnosticForSpan(diagnosticLevel, firstItem.NameSource.Span, MaxNumber) };
Expand Down
6 changes: 0 additions & 6 deletions src/Bicep.Core/Emit/EmitterContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT License.
using System.Collections.Immutable;
using Bicep.Core.DataFlow;
using Bicep.Core.Emit.CompileTimeImports;
using Bicep.Core.Semantics;
using Bicep.Core.Semantics.Metadata;
using Bicep.Core.Syntax;
Expand All @@ -12,8 +11,6 @@ namespace Bicep.Core.Emit
{
public class EmitterContext
{
private readonly Lazy<ImportClosureInfo> importClosureInfoLazy;

public EmitterContext(SemanticModel semanticModel)
{
Settings = semanticModel.EmitterSettings;
Expand All @@ -22,7 +19,6 @@ public EmitterContext(SemanticModel semanticModel)
VariablesToInline = InlineDependencyVisitor.GetVariablesToInline(semanticModel);
ResourceDependencies = ResourceDependencyVisitor.GetResourceDependencies(semanticModel);
FunctionVariables = FunctionVariableGeneratorVisitor.GetFunctionVariables(semanticModel);
importClosureInfoLazy = new(() => ImportClosureInfo.Calculate(semanticModel), LazyThreadSafetyMode.PublicationOnly);
}

public EmitterSettings Settings { get; }
Expand All @@ -40,7 +36,5 @@ public EmitterContext(SemanticModel semanticModel)
public ImmutableDictionary<ModuleSymbol, ScopeHelper.ScopeData> ModuleScopeData => SemanticModel.EmitLimitationInfo.ModuleScopeData;

public ImmutableDictionary<DeclaredResourceMetadata, ScopeHelper.ScopeData> ResourceScopeData => SemanticModel.EmitLimitationInfo.ResourceScopeData;

public ImportClosureInfo ImportClosureInfo => importClosureInfoLazy.Value;
}
}
8 changes: 4 additions & 4 deletions src/Bicep.Core/Emit/ExpressionConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public LanguageExpression ConvertExpression(Expression expression)

case ImportedUserDefinedFunctionCallExpression importedFunction:
{
var (namespaceName, functionName) = GetFunctionName(context.ImportClosureInfo.ImportedSymbolNames[importedFunction.Symbol]);
var (namespaceName, functionName) = GetFunctionName(context.SemanticModel.ImportClosureInfo.ImportedSymbolNames[importedFunction.Symbol]);
return CreateFunction(
$"{namespaceName}.{functionName}",
importedFunction.Parameters.Select(ConvertExpression));
Expand All @@ -119,7 +119,7 @@ public LanguageExpression ConvertExpression(Expression expression)
case WildcardImportInstanceFunctionCallExpression importedFunction:
{
var (namespaceName, functionName) = GetFunctionName(
context.ImportClosureInfo.WildcardImportPropertyNames[new(importedFunction.ImportSymbol, importedFunction.MethodName)]);
context.SemanticModel.ImportClosureInfo.WildcardImportPropertyNames[new(importedFunction.ImportSymbol, importedFunction.MethodName)]);
return CreateFunction(
$"{namespaceName}.{functionName}",
importedFunction.Parameters.Select(ConvertExpression));
Expand Down Expand Up @@ -167,11 +167,11 @@ public LanguageExpression ConvertExpression(Expression expression)
return CreateFunction("variables", new JTokenExpression(exp.Name));

case ImportedVariableReferenceExpression exp:
return CreateFunction("variables", new JTokenExpression(context.ImportClosureInfo.ImportedSymbolNames[exp.Variable]));
return CreateFunction("variables", new JTokenExpression(context.SemanticModel.ImportClosureInfo.ImportedSymbolNames[exp.Variable]));

case WildcardImportVariablePropertyReferenceExpression exp:
return CreateFunction("variables",
new JTokenExpression(context.ImportClosureInfo.WildcardImportPropertyNames[new(exp.ImportSymbol, exp.PropertyName)]));
new JTokenExpression(context.SemanticModel.ImportClosureInfo.WildcardImportPropertyNames[new(exp.ImportSymbol, exp.PropertyName)]));

case ParametersReferenceExpression exp:
return CreateFunction("parameters", new JTokenExpression(exp.Parameter.Name));
Expand Down
6 changes: 3 additions & 3 deletions src/Bicep.Core/Emit/ParameterAssignmentEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ public ParameterAssignmentEvaluator(SemanticModel model)

EmitterContext context = new(model);
this.converter = new(context);
this.importsByName = context.ImportClosureInfo.ImportedSymbolNames.Keys
.Select(importedVariable => (context.ImportClosureInfo.ImportedSymbolNames[importedVariable], importedVariable))
this.importsByName = context.SemanticModel.ImportClosureInfo.ImportedSymbolNames.Keys
.Select(importedVariable => (context.SemanticModel.ImportClosureInfo.ImportedSymbolNames[importedVariable], importedVariable))
.GroupBy(x => x.Item1, LanguageConstants.IdentifierComparer)
.ToImmutableDictionary(x => x.Key, x => x.First().importedVariable, LanguageConstants.IdentifierComparer);
this.wildcardImportPropertiesByName = context.ImportClosureInfo.WildcardImportPropertyNames
this.wildcardImportPropertiesByName = context.SemanticModel.ImportClosureInfo.WildcardImportPropertyNames
.GroupBy(x => x.Value, LanguageConstants.IdentifierComparer)
.ToImmutableDictionary(x => x.Key, x => x.First().Key, LanguageConstants.IdentifierComparer);
this.synthesizedVariableValuesByName = context.FunctionVariables.Values
Expand Down
16 changes: 8 additions & 8 deletions src/Bicep.Core/Emit/TemplateWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void Write(SourceAwareJsonTextWriter writer)

var program = (ProgramExpression)ExpressionBuilder.Convert(Context.SemanticModel.Root.Syntax);

var programTypes = program.Types.Concat(Context.ImportClosureInfo.ImportedTypesInClosure);
var programTypes = program.Types.Concat(Context.SemanticModel.ImportClosureInfo.ImportedTypesInClosure);
declaredTypesByName = programTypes.ToImmutableDictionary(t => t.Name);

jsonWriter.WriteStartObject();
Expand Down Expand Up @@ -128,11 +128,11 @@ public void Write(SourceAwareJsonTextWriter writer)

this.EmitTypeDefinitionsIfPresent(emitter, programTypes);

this.EmitUserDefinedFunctions(emitter, program.Functions.Concat(Context.ImportClosureInfo.ImportedFunctionsInClosure));
this.EmitUserDefinedFunctions(emitter, program.Functions.Concat(Context.SemanticModel.ImportClosureInfo.ImportedFunctionsInClosure));

this.EmitParametersIfPresent(emitter, program.Parameters);

this.EmitVariablesIfPresent(emitter, program.Variables.Concat(Context.ImportClosureInfo.ImportedVariablesInClosure));
this.EmitVariablesIfPresent(emitter, program.Variables.Concat(Context.SemanticModel.ImportClosureInfo.ImportedVariablesInClosure));

this.EmitExtensionsIfPresent(emitter, program.Extensions);

Expand Down Expand Up @@ -315,7 +315,7 @@ private void EmitUserDefinedFunction(ExpressionEmitter emitter, DeclaredFunction
? function.Name
: $"{function.Namespace}.{function.Name}";

if (function.Description is not null || function.Exported is not null || Context.ImportClosureInfo.ImportedSymbolOriginMetadata.ContainsKey(originMetadataLookupKey))
if (function.Description is not null || function.Exported is not null || Context.SemanticModel.ImportClosureInfo.ImportedSymbolOriginMetadata.ContainsKey(originMetadataLookupKey))
{
emitter.EmitObjectProperty(LanguageConstants.ParameterMetadataPropertyName, () =>
{
Expand All @@ -329,7 +329,7 @@ private void EmitUserDefinedFunction(ExpressionEmitter emitter, DeclaredFunction
emitter.EmitProperty(LanguageConstants.MetadataExportedPropertyName, ExpressionFactory.CreateBooleanLiteral(true, function.Exported.SourceSyntax));
}

if (Context.ImportClosureInfo.ImportedSymbolOriginMetadata.TryGetValue(originMetadataLookupKey, out var originMetadata))
if (Context.SemanticModel.ImportClosureInfo.ImportedSymbolOriginMetadata.TryGetValue(originMetadataLookupKey, out var originMetadata))
{
emitter.EmitObjectProperty(LanguageConstants.MetadataImportedFromPropertyName, () =>
{
Expand Down Expand Up @@ -363,7 +363,7 @@ private void EmitTypeDeclaration(ExpressionEmitter emitter, DeclaredTypeExpressi
() =>
{
var declaredTypeObject = ApplyTypeModifiers(declaredType, TypePropertiesForTypeExpression(declaredType.Value));
if (Context.ImportClosureInfo.ImportedSymbolOriginMetadata.TryGetValue(declaredType.Name, out var originMetadata))
if (Context.SemanticModel.ImportClosureInfo.ImportedSymbolOriginMetadata.TryGetValue(declaredType.Name, out var originMetadata))
{
var importedFromProperties = ExpressionFactory.CreateObjectProperty(LanguageConstants.ImportMetadataSourceTemplatePropertyName,
ExpressionFactory.CreateStringLiteral(originMetadata.SourceTemplateIdentifier)).AsEnumerable();
Expand Down Expand Up @@ -542,9 +542,9 @@ private ITypeReferenceExpressionResolution ResolveTypeReferenceExpression(TypeEx
TypeAliasReferenceExpression typeAliasReference => ForNamedRoot(typeAliasReference.Symbol.Name),
SynthesizedTypeAliasReferenceExpression typeAliasReference => ForNamedRoot(typeAliasReference.Name),
ImportedTypeReferenceExpression importedTypeReference => ForNamedRoot(
Context.ImportClosureInfo.ImportedSymbolNames[importedTypeReference.Symbol]),
Context.SemanticModel.ImportClosureInfo.ImportedSymbolNames[importedTypeReference.Symbol]),
WildcardImportTypePropertyReferenceExpression importedTypeReference => ForNamedRoot(
Context.ImportClosureInfo.WildcardImportPropertyNames[new(importedTypeReference.ImportSymbol, importedTypeReference.PropertyName)]),
Context.SemanticModel.ImportClosureInfo.WildcardImportPropertyNames[new(importedTypeReference.ImportSymbol, importedTypeReference.PropertyName)]),
ResourceDerivedTypeExpression resourceDerived => new ResourceDerivedTypeResolution(resourceDerived),
_ => throw new ArgumentException($"Cannot resolve type reference access expression with a root of type '{root.GetType().Name}'."),
};
Expand Down
5 changes: 5 additions & 0 deletions src/Bicep.Core/Semantics/SemanticModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Bicep.Core.Configuration;
using Bicep.Core.Diagnostics;
using Bicep.Core.Emit;
using Bicep.Core.Emit.CompileTimeImports;
using Bicep.Core.Extensions;
using Bicep.Core.Features;
using Bicep.Core.Registry;
Expand All @@ -37,6 +38,7 @@ public class SemanticModel : ISemanticModel
private readonly Lazy<ImmutableArray<OutputMetadata>> outputsLazy;
private readonly Lazy<IApiVersionProvider> apiVersionProviderLazy;
private readonly Lazy<EmitterSettings> emitterSettingsLazy;
private readonly Lazy<ImportClosureInfo> importClosureInfoLazy;

// needed to support param file go to def
private readonly Lazy<ImmutableDictionary<ParameterAssignmentSymbol, ParameterMetadata?>> declarationsByAssignment;
Expand Down Expand Up @@ -89,6 +91,7 @@ public SemanticModel(IBicepAnalyzer linterAnalyzer, INamespaceProvider namespace

this.emitterSettingsLazy = new(() => new(this));
this.emitLimitationInfoLazy = new(() => EmitLimitationCalculator.Calculate(this));
this.importClosureInfoLazy = new(() => ImportClosureInfo.Calculate(this));
this.symbolHierarchyLazy = new(() =>
{
var hierarchy = new SymbolHierarchy();
Expand Down Expand Up @@ -242,6 +245,8 @@ private static void TraceBuildOperation(BicepSourceFile sourceFile, IFeatureProv

public EmitLimitationInfo EmitLimitationInfo => emitLimitationInfoLazy.Value;

public ImportClosureInfo ImportClosureInfo => importClosureInfoLazy.Value;

public ResourceAncestorGraph ResourceAncestors => resourceAncestorsLazy.Value;

public ResourceMetadataCache ResourceMetadata { get; }
Expand Down
Loading