Example #1
0
        private void EmitModule(ModuleSymbol moduleSymbol)
        {
            writer.WriteStartObject();

            this.emitter.EmitProperty("type", NestedDeploymentResourceType);
            this.emitter.EmitProperty("apiVersion", NestedDeploymentResourceApiVersion);

            // emit all properties apart from 'params'. In practice, this currrently only allows 'name', but we may choose to allow other top-level resource properties in future.
            // params requires special handling (see below).
            var moduleBody = (ObjectSyntax)moduleSymbol.DeclaringModule.Body;

            this.emitter.EmitObjectProperties(moduleBody, ModulePropertiesToOmit);

            var scopeData = context.ModuleScopeData[moduleSymbol];

            ScopeHelper.EmitModuleScopeProperties(scopeData, emitter);

            writer.WritePropertyName("properties");
            {
                writer.WriteStartObject();

                writer.WritePropertyName("expressionEvaluationOptions");
                {
                    writer.WriteStartObject();
                    this.emitter.EmitProperty("scope", "inner");
                    writer.WriteEndObject();
                }

                this.emitter.EmitProperty("mode", "Incremental");

                EmitModuleParameters(moduleSymbol);

                writer.WritePropertyName("template");
                {
                    var moduleSemanticModel = GetModuleSemanticModel(moduleSymbol);
                    var moduleWriter        = new TemplateWriter(writer, moduleSemanticModel);
                    moduleWriter.Write();
                }

                writer.WriteEndObject();
            }

            this.EmitDependsOn(moduleSymbol);

            writer.WriteEndObject();
        }
        private void EmitModule(JsonTextWriter jsonWriter, ModuleSymbol moduleSymbol, ExpressionEmitter emitter)
        {
            jsonWriter.WriteStartObject();

            var body = moduleSymbol.DeclaringModule.Value;

            switch (body)
            {
            case IfConditionSyntax ifCondition:
                body = ifCondition.Body;
                emitter.EmitProperty("condition", ifCondition.ConditionExpression);
                break;

            case ForSyntax @for:
                if (@for.Body is IfConditionSyntax loopFilter)
                {
                    body = loopFilter.Body;
                    emitter.EmitProperty("condition", loopFilter.ConditionExpression);
                }
                else
                {
                    body = @for.Body;
                }

                var batchSize = GetBatchSize(moduleSymbol.DeclaringModule);
                emitter.EmitProperty("copy", () => emitter.EmitCopyObject(moduleSymbol.Name, @for, input: null, batchSize: batchSize));
                break;
            }

            emitter.EmitProperty("type", NestedDeploymentResourceType);
            emitter.EmitProperty("apiVersion", NestedDeploymentResourceApiVersion);

            // emit all properties apart from 'params'. In practice, this currrently only allows 'name', but we may choose to allow other top-level resource properties in future.
            // params requires special handling (see below).
            emitter.EmitObjectProperties((ObjectSyntax)body, ModulePropertiesToOmit);

            var scopeData = context.ModuleScopeData[moduleSymbol];

            ScopeHelper.EmitModuleScopeProperties(context.SemanticModel.TargetScope, scopeData, emitter, body);

            if (scopeData.RequestedScope != ResourceScope.ResourceGroup)
            {
                // if we're deploying to a scope other than resource group, we need to supply a location
                if (this.context.SemanticModel.TargetScope == ResourceScope.ResourceGroup)
                {
                    // the deployment() object at resource group scope does not contain a property named 'location', so we have to use resourceGroup().location
                    emitter.EmitProperty("location", new FunctionExpression(
                                             "resourceGroup",
                                             Array.Empty <LanguageExpression>(),
                                             new LanguageExpression[] { new JTokenExpression("location") }));
                }
                else
                {
                    // at all other scopes we can just use deployment().location
                    emitter.EmitProperty("location", new FunctionExpression(
                                             "deployment",
                                             Array.Empty <LanguageExpression>(),
                                             new LanguageExpression[] { new JTokenExpression("location") }));
                }
            }

            jsonWriter.WritePropertyName("properties");
            {
                jsonWriter.WriteStartObject();

                jsonWriter.WritePropertyName("expressionEvaluationOptions");
                {
                    jsonWriter.WriteStartObject();
                    emitter.EmitProperty("scope", "inner");
                    jsonWriter.WriteEndObject();
                }

                emitter.EmitProperty("mode", "Incremental");

                EmitModuleParameters(jsonWriter, moduleSymbol, emitter);

                var moduleSemanticModel = GetModuleSemanticModel(moduleSymbol);

                // If it is a template spec module, emit templateLink instead of template contents.
                jsonWriter.WritePropertyName(moduleSemanticModel is TemplateSpecSemanticModel ? "templateLink" : "template");
                {
                    TemplateWriterFactory.CreateTemplateWriter(moduleSemanticModel, this.settings).Write(jsonWriter);
                }

                jsonWriter.WriteEndObject();
            }

            this.EmitDependsOn(jsonWriter, moduleSymbol, emitter, body);

            // Since we don't want to be mutating the body of the original ObjectSyntax, we create an placeholder body in place
            // and emit its properties to merge decorator properties.
            foreach (var(property, val) in AddDecoratorsToBody(
                         moduleSymbol.DeclaringModule,
                         SyntaxFactory.CreateObject(Enumerable.Empty <ObjectPropertySyntax>()),
                         moduleSymbol.Type).ToNamedPropertyValueDictionary())
            {
                emitter.EmitProperty(property, val);
            }

            jsonWriter.WriteEndObject();
        }
Example #3
0
        private void EmitModule(ModuleSymbol moduleSymbol)
        {
            writer.WriteStartObject();

            if (moduleSymbol.DeclaringModule.IfCondition is IfConditionSyntax ifCondition)
            {
                this.emitter.EmitProperty("condition", ifCondition.ConditionExpression);
            }

            this.emitter.EmitProperty("type", NestedDeploymentResourceType);
            this.emitter.EmitProperty("apiVersion", NestedDeploymentResourceApiVersion);

            // emit all properties apart from 'params'. In practice, this currrently only allows 'name', but we may choose to allow other top-level resource properties in future.
            // params requires special handling (see below).
            this.emitter.EmitObjectProperties((ObjectSyntax)moduleSymbol.DeclaringModule.Body, ModulePropertiesToOmit);


            var scopeData = context.ModuleScopeData[moduleSymbol];

            ScopeHelper.EmitModuleScopeProperties(scopeData, emitter);

            if (scopeData.RequestedScope != ResourceScopeType.ResourceGroupScope)
            {
                // if we're deploying to a scope other than resource group, we need to supply a location
                if (this.context.SemanticModel.TargetScope == ResourceScopeType.ResourceGroupScope)
                {
                    // the deployment() object at resource group scope does not contain a property named 'location', so we have to use resourceGroup().location
                    this.emitter.EmitProperty("location", new FunctionExpression(
                                                  "resourceGroup",
                                                  new LanguageExpression[] { },
                                                  new LanguageExpression[] { new JTokenExpression("location") }));
                }
                else
                {
                    // at all other scopes we can just use deployment().location
                    this.emitter.EmitProperty("location", new FunctionExpression(
                                                  "deployment",
                                                  new LanguageExpression[] { },
                                                  new LanguageExpression[] { new JTokenExpression("location") }));
                }
            }

            writer.WritePropertyName("properties");
            {
                writer.WriteStartObject();

                writer.WritePropertyName("expressionEvaluationOptions");
                {
                    writer.WriteStartObject();
                    this.emitter.EmitProperty("scope", "inner");
                    writer.WriteEndObject();
                }

                this.emitter.EmitProperty("mode", "Incremental");

                EmitModuleParameters(moduleSymbol);

                writer.WritePropertyName("template");
                {
                    var moduleSemanticModel = GetModuleSemanticModel(moduleSymbol);
                    var moduleWriter        = new TemplateWriter(writer, moduleSemanticModel);
                    moduleWriter.Write();
                }

                writer.WriteEndObject();
            }

            this.EmitDependsOn(moduleSymbol);

            writer.WriteEndObject();
        }