public override void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.Source.HasValue) { using (context.CodeWriter.BuildLinePragma(node.Source.Value)) { context.AddSourceMappingFor(node); context.CodeWriter.WriteUsing(node.Content); } } else { context.CodeWriter.WriteUsing(node.Content); } }
private void WriteMarkerToken(CodeRenderingContext context, DirectiveTokenIntermediateNode node) { // We want to map marker tokens to a location in the generated document // that will provide CSharp intellisense. context.AddSourceMappingFor(node); context.CodeWriter.Write(" "); }
public override void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node) { if (node.Source.HasValue) { using (context.CodeWriter.BuildLinePragma(node.Source.Value, context)) { context.AddSourceMappingFor(node); context.CodeWriter.WriteUsing(node.Content); } } else { context.CodeWriter.WriteUsing(node.Content); } }
public override void WriteCSharpCode(CodeRenderingContext context, CSharpCodeIntermediateNode node) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (node == null) { throw new ArgumentNullException(nameof(node)); } var isWhitespaceStatement = true; for (var i = 0; i < node.Children.Count; i++) { var token = node.Children[i] as IntermediateToken; if (token == null || !string.IsNullOrWhiteSpace(token.Content)) { isWhitespaceStatement = false; break; } } if (isWhitespaceStatement) { // The runtime and design time code differ in their handling of whitespace-only // statements. At runtime we can discard them completely. At design time we need // to keep them for the editor. return; } IDisposable linePragmaScope = null; if (node.Source != null) { linePragmaScope = context.CodeWriter.BuildLinePragma(node.Source.Value); context.CodeWriter.WritePadding(0, node.Source.Value, context); } for (var i = 0; i < node.Children.Count; i++) { if (node.Children[i] is IntermediateToken token && token.IsCSharp) { _scopeStack.IncrementCurrentScopeChildCount(context); context.AddSourceMappingFor(token); context.CodeWriter.Write(token.Content); }
private void WriteMarkerToken(CodeRenderingContext context, DirectiveTokenIntermediateNode node) { // Marker tokens exist to be filled with other content a user might write. In an end-to-end // scenario markers prep the Razor documents C# projections to have an empty projection that // can be filled with other user content. This content can trigger a multitude of other events, // such as completion. In the case of completion, a completion session can occur when a marker // hasn't been filled and then we will fill it as a user types. The line pragma is necessary // for consistency so when a C# completion session starts, filling user code doesn't result in // a previously non-existent line pragma from being added and destroying the context in which // the completion session was started. using (context.CodeWriter.BuildLinePragma(node.Source, context)) { context.AddSourceMappingFor(node); context.CodeWriter.Write(" "); } }
private void WriteCSharpExpressionInnards(CodeRenderingContext context, CSharpExpressionIntermediateNode node, string type = null) { if (node.Children.Count == 0) { return; } if (node.Source != null) { using (context.CodeWriter.BuildLinePragma(node.Source.Value, context)) { var offset = DesignTimeVariable.Length + " = ".Length; if (type != null) { offset += type.Length + 2; // two parenthesis } context.CodeWriter.WritePadding(offset, node.Source, context); context.CodeWriter.WriteStartAssignment(DesignTimeVariable); if (type != null) { context.CodeWriter.Write("("); context.CodeWriter.Write(type); context.CodeWriter.Write(")"); } for (var i = 0; i < node.Children.Count; i++) { if (node.Children[i] is IntermediateToken token && token.IsCSharp) { context.AddSourceMappingFor(token); context.CodeWriter.Write(token.Content); } else { // There may be something else inside the expression like a Template or another extension node. context.RenderNode(node.Children[i]); } }
public override void WriteCSharpExpression(CodeRenderingContext context, CSharpExpressionIntermediateNode node) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.Children.Count == 0) { return; } if (node.Source != null) { using (context.CodeWriter.BuildLinePragma(node.Source.Value)) { var offset = DesignTimeVariable.Length + " = ".Length; context.CodeWriter.WritePadding(offset, node.Source, context); context.CodeWriter.WriteStartAssignment(DesignTimeVariable); for (var i = 0; i < node.Children.Count; i++) { if (node.Children[i] is IntermediateToken token && token.IsCSharp) { context.AddSourceMappingFor(token); context.CodeWriter.Write(token.Content); } else { // There may be something else inside the expression like a Template or another extension node. context.RenderNode(node.Children[i]); } }
private void WriteDesignTimeDirectiveToken(CodeRenderingContext context, DesignTimeDirectiveIntermediateNode parent, DirectiveTokenIntermediateNode node, int currentIndex) { var tokenKind = node.DirectiveToken.Kind; if (!node.Source.HasValue || !string.Equals( context.SourceDocument?.FilePath, node.Source.Value.FilePath, StringComparison.OrdinalIgnoreCase)) { // We don't want to handle directives from imports. return; } if (tokenKind == DirectiveTokenKind.Attribute) { // We don't need to do anything special here. // We let the Roslyn take care of providing syntax errors for C# attributes. return; } // Wrap the directive token in a lambda to isolate variable names. context.CodeWriter .Write("((") .Write(typeof(Action).FullName) .Write(")("); using (context.CodeWriter.BuildLambda()) { var originalIndent = context.CodeWriter.CurrentIndent; context.CodeWriter.CurrentIndent = 0; switch (tokenKind) { case DirectiveTokenKind.Type: if (string.IsNullOrEmpty(node.Content)) { // This is most likely a marker token. WriteMarkerToken(context, node); break; } // {node.Content} __typeHelper = default({node.Content}); using (context.CodeWriter.BuildLinePragma(node.Source, context)) { context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .Write(" ") .WriteStartAssignment(TypeHelper) .Write("default"); if (!context.Options.SuppressNullabilityEnforcement) { context.CodeWriter.Write("!"); } context.CodeWriter.WriteLine(";"); } break; case DirectiveTokenKind.Member: if (string.IsNullOrEmpty(node.Content)) { // This is most likely a marker token. WriteMarkerToken(context, node); break; } // global::System.Object {node.content} = null; using (context.CodeWriter.BuildLinePragma(node.Source, context)) { context.CodeWriter .Write("global::") .Write(typeof(object).FullName) .Write(" "); context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .Write(" = null"); if (!context.Options.SuppressNullabilityEnforcement) { context.CodeWriter.Write("!"); } context.CodeWriter.WriteLine(";"); } break; case DirectiveTokenKind.Namespace: if (string.IsNullOrEmpty(node.Content)) { // This is most likely a marker token. WriteMarkerToken(context, node); break; } // global::System.Object __typeHelper = nameof({node.Content}); using (context.CodeWriter.BuildLinePragma(node.Source, context)) { context.CodeWriter .Write("global::") .Write(typeof(object).FullName) .Write(" ") .WriteStartAssignment(TypeHelper); context.CodeWriter.Write("nameof("); context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .WriteLine(");"); } break; case DirectiveTokenKind.String: // global::System.Object __typeHelper = "{node.Content}"; using (context.CodeWriter.BuildLinePragma(node.Source, context)) { context.CodeWriter .Write("global::") .Write(typeof(object).FullName) .Write(" ") .WriteStartAssignment(TypeHelper); if (node.Content.StartsWith("\"", StringComparison.Ordinal)) { context.AddSourceMappingFor(node); context.CodeWriter.Write(node.Content); } else { context.CodeWriter.Write("\""); context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .Write("\""); } context.CodeWriter.WriteLine(";"); } break; case DirectiveTokenKind.Boolean: // global::System.Boolean __typeHelper = {node.Content}; using (context.CodeWriter.BuildLinePragma(node.Source, context)) { context.CodeWriter .Write("global::") .Write(typeof(bool).FullName) .Write(" ") .WriteStartAssignment(TypeHelper); context.AddSourceMappingFor(node); context.CodeWriter.Write(node.Content); context.CodeWriter.WriteLine(";"); } break; case DirectiveTokenKind.GenericTypeConstraint: // We generate a generic local function with a generic parameter using the // same name and apply the constraints, like below. // The two warnings that we disable are: // * Hiding the class type parameter with the parameter on the method // * The function is defined but not used. // static void TypeConstraints_TParamName<TParamName>() where TParamName ...; context.CodeWriter.WriteLine("#pragma warning disable CS0693"); context.CodeWriter.WriteLine("#pragma warning disable CS8321"); using (context.CodeWriter.BuildLinePragma(node.Source, context)) { // It's OK to do this since a GenericTypeParameterConstraint token is always preceded by a member token. var genericTypeParamName = (DirectiveTokenIntermediateNode)parent.Children[currentIndex - 1]; context.CodeWriter .Write("void __TypeConstraints_") .Write(genericTypeParamName.Content) .Write("<") .Write(genericTypeParamName.Content) .Write(">() "); context.AddSourceMappingFor(node); context.CodeWriter.Write(node.Content); context.CodeWriter.WriteLine(); context.CodeWriter.WriteLine("{"); context.CodeWriter.WriteLine("}"); context.CodeWriter.WriteLine("#pragma warning restore CS0693"); context.CodeWriter.WriteLine("#pragma warning restore CS8321"); } break; } context.CodeWriter.CurrentIndent = originalIndent; } context.CodeWriter.WriteLine("))();"); }
private void WriteDesignTimeDirectiveToken(CodeRenderingContext context, DirectiveTokenIntermediateNode node) { var tokenKind = node.DirectiveToken.Kind; if (!node.Source.HasValue || !string.Equals( context.SourceDocument?.FilePath, node.Source.Value.FilePath, StringComparison.OrdinalIgnoreCase)) { // We don't want to handle directives from imports. return; } // Wrap the directive token in a lambda to isolate variable names. context.CodeWriter .Write("((") .Write(typeof(Action).FullName) .Write(")("); using (context.CodeWriter.BuildLambda()) { var originalIndent = context.CodeWriter.CurrentIndent; context.CodeWriter.CurrentIndent = 0; switch (tokenKind) { case DirectiveTokenKind.Type: if (string.IsNullOrEmpty(node.Content)) { // This is most likely a marker token. WriteMarkerToken(context, node); break; } // {node.Content} __typeHelper = default({node.Content}); using (context.CodeWriter.BuildLinePragma(node.Source)) { context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .Write(" ") .WriteStartAssignment(TypeHelper) .Write("default(") .Write(node.Content) .WriteLine(");"); } break; case DirectiveTokenKind.Member: if (string.IsNullOrEmpty(node.Content)) { // This is most likely a marker token. WriteMarkerToken(context, node); break; } // global::System.Object {node.content} = null; using (context.CodeWriter.BuildLinePragma(node.Source)) { context.CodeWriter .Write("global::") .Write(typeof(object).FullName) .Write(" "); context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .WriteLine(" = null;"); } break; case DirectiveTokenKind.Namespace: if (string.IsNullOrEmpty(node.Content)) { // This is most likely a marker token. WriteMarkerToken(context, node); break; } // global::System.Object __typeHelper = nameof({node.Content}); using (context.CodeWriter.BuildLinePragma(node.Source)) { context.CodeWriter .Write("global::") .Write(typeof(object).FullName) .Write(" ") .WriteStartAssignment(TypeHelper); context.CodeWriter.Write("nameof("); context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .WriteLine(");"); } break; case DirectiveTokenKind.String: // global::System.Object __typeHelper = "{node.Content}"; using (context.CodeWriter.BuildLinePragma(node.Source)) { context.CodeWriter .Write("global::") .Write(typeof(object).FullName) .Write(" ") .WriteStartAssignment(TypeHelper); if (node.Content.StartsWith("\"", StringComparison.Ordinal)) { context.AddSourceMappingFor(node); context.CodeWriter.Write(node.Content); } else { context.CodeWriter.Write("\""); context.AddSourceMappingFor(node); context.CodeWriter .Write(node.Content) .Write("\""); } context.CodeWriter.WriteLine(";"); } break; } context.CodeWriter.CurrentIndent = originalIndent; } context.CodeWriter.WriteLine("))();"); }