// Special case for statement padding to account for brace positioning in the editor. public static string PadStatement(RazorEngineHost host, string code, Span target, ref int startGeneratedCode, out int paddingCharCount) { if (host == null) { throw new ArgumentNullException("host"); } if (target == null) { throw new ArgumentNullException("target"); } // We are passing 0 rather than startgeneratedcode intentionally (keeping v2 behavior). int padding = CalculatePadding(host, target, 0); // We treat statement padding specially so for brace positioning, so that in the following example: // @if (foo > 0) // { // } // // the braces shows up under the @ rather than under the if. if (host.DesignTimeMode && padding > 0 && target.Previous.Kind == SpanKind.Transition && // target.Previous is guaranteed to be none null if you got any padding. String.Equals(target.Previous.Content, SyntaxConstants.TransitionString)) { padding--; startGeneratedCode--; } string generatedCode = PadInternal(host, code, padding, out paddingCharCount); return generatedCode; }
protected override bool TryVisitSpecialSpan(Span span) { var vistors = (Vistors ?? Enumerable.Empty<CSharpRazorCodeGeneratorSpanVisitor>()); return base.TryVisitSpecialSpan(span) || vistors.FirstOrDefault(x => x.TryVisit(span)) != null; }
public override void GenerateCode(Span target, CodeGeneratorContext context) { context.FlushBufferedStatement(); string generatedCode = context.BuildCodeString(cw => { cw.WriteSnippet(target.Content); }); int startGeneratedCode = target.Start.CharacterIndex; generatedCode = Pad(generatedCode, target); // Is this the span immediately following "@"? if (context.Host.DesignTimeMode && !String.IsNullOrEmpty(generatedCode) && Char.IsWhiteSpace(generatedCode[0]) && target.Previous != null && target.Previous.Kind == SpanKind.Transition && String.Equals(target.Previous.Content, SyntaxConstants.TransitionString)) { generatedCode = generatedCode.Substring(1); startGeneratedCode--; } context.AddStatement( generatedCode, context.GenerateLinePragma(target, startGeneratedCode)); }
public override void GenerateCode(Span target, CodeGeneratorContext context) { // Try to find the namespace in the existing imports string ns = Namespace; if (!String.IsNullOrEmpty(ns) && Char.IsWhiteSpace(ns[0])) { ns = ns.Substring(1); } CodeNamespaceImport import = context.Namespace .Imports .OfType<CodeNamespaceImport>() .Where(i => String.Equals(i.Namespace, ns.Trim(), StringComparison.Ordinal)) .FirstOrDefault(); if (import == null) { // It doesn't exist, create it import = new CodeNamespaceImport(ns); context.Namespace.Imports.Add(import); } // Attach our info to the existing/new import. import.LinePragma = context.GenerateLinePragma(target); }
public CodeBlockInfo(string name, SourceLocation start, bool isTopLevel, Span transitionSpan, Span initialSpan) { Name = name; Start = start; IsTopLevel = isTopLevel; TransitionSpan = transitionSpan; InitialSpan = initialSpan; }
public IEnumerable<Node> Parse(Span span) { return new[] { new ExpressionNode(span.Content) }; }
public override void GenerateCode (Span target, CodeGeneratorContext context) { if (context.Host.DesignTimeMode) return; ExpressionRenderingMode oldMode = context.GetExpressionRenderingMode (); var sb = new StringBuilder (); sb.Append (", Tuple.Create<string,object,bool> ("); sb.WriteCStyleStringLiteral (Prefix.Value); sb.Append (", "); if (ValueGenerator != null) { context.SetExpressionRenderingMode (ExpressionRenderingMode.InjectCode); } else { sb.WriteCStyleStringLiteral (Value); sb.Append (", true)"); } context.BufferStatementFragment (sb.ToString ()); if (ValueGenerator != null) { ValueGenerator.Value.GenerateCode (target, context); context.FlushBufferedStatement (); context.SetExpressionRenderingMode (oldMode); context.AddStatement (", false)"); } else { context.FlushBufferedStatement (); } }
// internal for unit testing only, not intended to be used directly in code internal static int CalculatePadding(RazorEngineHost host, Span target, int generatedStart) { if (host == null) { throw new ArgumentNullException("host"); } if (target == null) { throw new ArgumentNullException("target"); } int padding; padding = CollectSpacesAndTabs(target, host.TabSize) - generatedStart; // if we add generated text that is longer than the padding we wanted to insert we have no recourse and we have to skip padding // example: // Razor code at column zero: @somecode() // Generated code will be: // In design time: __o = somecode(); // In Run time: Write(somecode()); // // In both cases the padding would have been 1 space to remote the space the @ symbol takes, which will be smaller than the 6 chars the hidden generated code takes. if (padding < 0) { padding = 0; } return padding; }
public override void GenerateCode(Span target, CodeGeneratorContext context) { // We parsed: "@contentType Text.Html" // And we assigned this code generator to the "Text.Html" part // So this node's content should be "Text.Html" string contentType = target.Content; // The final code we want is something like // Response.ContentType = ContentTypes.Text.Html; // So, we start by injecting the "prolog" (this is compiler speak for the stuff before the user code) context.BufferStatementFragment("Response.ContentType = ContentTypes."); // Now we tell the code generator infrastructure that we're at the start of user code // This allows us to inject markers so the editor can light up. context.MarkStartOfGeneratedCode(); // Here's our user code! context.BufferStatementFragment(contentType); // And we tell Razor we're finished with user code, again for the editor context.MarkEndOfGeneratedCode(); // Finally, we inject the "epilog" (compiler speak for stuff after the user code) context.BufferStatementFragment(";"); // And output the whole statement to the generated Execute method context.FlushBufferedStatement(); }
public virtual bool OwnsChange(Span target, TextChange change) { int end = target.Start.AbsoluteIndex + target.Length; int changeOldEnd = change.OldPosition + change.OldLength; return change.OldPosition >= target.Start.AbsoluteIndex && (changeOldEnd < end || (changeOldEnd == end && AcceptedCharacters != AcceptedCharacters.None)); }
private int?GetDesiredIndentationHelper(ITextSnapshotLine line) { int?num = null; if (IsSmartIndentEnabled() && line.LineNumber > 0 && RazorCodeGenerator != null) { ITextSnapshotLine lineFromLineNumber = line.Snapshot.GetLineFromLineNumber(line.LineNumber - 1); Block document = RazorCodeGenerator.Document; System.Web.Razor.Text.ITextBuffer textBuffer = new ShimTextBufferAdapter(lineFromLineNumber.Snapshot); TextChange change = new TextChange(lineFromLineNumber.End, 0, textBuffer, lineFromLineNumber.End, 0, textBuffer); Stack <Block> stack = new Stack <Block>(); System.Web.Razor.Parser.SyntaxTree.Span span = LocateOwner(document, change, stack); if (span.Kind != SpanKind.Code) { SyntaxTreeNode syntaxTreeNode = span; while (stack.Count > 0 && !num.HasValue) { Block block = stack.Pop(); List <SyntaxTreeNode> list = new List <SyntaxTreeNode>(block.Children); for (int i = 0; i < list.Count; i++) { SyntaxTreeNode syntaxTreeNode2 = list[i]; if (!syntaxTreeNode2.IsBlock) { System.Web.Razor.Parser.SyntaxTree.Span span2 = syntaxTreeNode2 as System.Web.Razor.Parser.SyntaxTree.Span; if (span2.Kind == SpanKind.MetaCode) { ITextSnapshotLine lineFromLineNumber2 = line.Snapshot.GetLineFromLineNumber(span2.Start.LineIndex); int num2 = 0; if (i < list.Count - 1) { SyntaxTreeNode syntaxTreeNode3 = list[i + 1]; if (syntaxTreeNode3.IsBlock && (syntaxTreeNode3 as Block).Type == BlockType.Markup) { num2 = _textView.Options.GetOptionValue <int>(DefaultOptions.IndentSizeOptionId); } } num = new int?(GetIndentLevelOfLine(lineFromLineNumber2) + num2); } } if (syntaxTreeNode2 == syntaxTreeNode) { break; } } syntaxTreeNode = block; } } } if (BaseIndenter != null) { int?desiredIndentation = BaseIndenter.GetDesiredIndentation(line); if (desiredIndentation.HasValue && (!num.HasValue || desiredIndentation > num)) { num = desiredIndentation; } } return(num); }
public SpanBuilder(Span original) { Kind = original.Kind; _symbols = new List<ISymbol>(original.Symbols); EditHandler = original.EditHandler; CodeGenerator = original.CodeGenerator; Start = original.Start; }
public override void GenerateCode(Span target, CodeGeneratorContext context) { base.GenerateCode(target, context); context.GeneratedClass.UserData.Add("ModelType", this.modelType); context.GeneratedClass.BaseTypes.Clear(); context.GeneratedClass.BaseTypes.Add(new CodeTypeReference(context.Host.DefaultBaseClass, new CodeTypeReference(this.modelType))); }
void VisitModelNameSpan(Span span) { if (span == null) return; string firstLineOfMarkup = GetFirstLine(span.Content); ModelTypeName = firstLineOfMarkup.Trim(); foundModelTypeName = true; }
public override void GenerateCode(Span target, CodeGeneratorContext context) { var attributeType = new CodeTypeReference(typeof(RazorDirectiveAttribute)); var attributeDeclaration = new CodeAttributeDeclaration( attributeType, new CodeAttributeArgument(new CodePrimitiveExpression(Name)), new CodeAttributeArgument(new CodePrimitiveExpression(Value))); context.GeneratedClass.CustomAttributes.Add(attributeDeclaration); }
protected internal static int CalculatePadding(Span target, int generatedStart) { int padding = target.Start.CharacterIndex - generatedStart; if (padding < 0) { padding = 0; } return padding; }
protected override SyntaxTreeNode RewriteSpan (BlockBuilder parent, Span span) { var b = new SpanBuilder (span); var old = (LiteralAttributeCodeGenerator)span.CodeGenerator; b.CodeGenerator = old.ValueGenerator != null ? new PreprocessedLiteralAttributeCodeGenerator (old.Prefix, old.ValueGenerator) : new PreprocessedLiteralAttributeCodeGenerator (old.Prefix, old.Value); return b.Build (); }
public override void GenerateCode(Span target, CodeGeneratorContext context) { Span sourceSpan = null; if (context.CreateCodeWriter().SupportsMidStatementLinePragmas || context.ExpressionRenderingMode == ExpressionRenderingMode.WriteToOutput) { sourceSpan = target; } context.BufferStatementFragment(target.Content, sourceSpan); }
public void CalculatePaddingForEmptySpanReturnsZero() { RazorEngineHost host = CreateHost(designTime: true); Span span = new Span(new SpanBuilder()); int padding = CodeGeneratorPaddingHelper.CalculatePadding(host, span, 0); Assert.Equal(0, padding); }
public override void GenerateCode(Span target, CodeGeneratorContext context) { if (!context.Host.DesignTimeMode && !String.IsNullOrEmpty(context.Host.GeneratedClassContext.LayoutPropertyName)) { context.TargetMethod.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(null, context.Host.GeneratedClassContext.LayoutPropertyName), new CodePrimitiveExpression(LayoutPath))); } }
public override void VisitSpan(Span span) { if (span.Kind == SpanKind.Markup && !m_DebugStatusReader.IsDebuggingEnabled()) { string content = span.Content; span.Content = m_HtmPagelMinifier.Minify(content, true, true); } base.VisitSpan(span); }
public override void GenerateCode(Span target, CodeGeneratorContext context) { if (context.Host.DesignTimeMode) { return; } ExpressionRenderingMode oldMode = context.ExpressionRenderingMode; context.BufferStatementFragment(context.BuildCodeString(cw => { cw.WriteParameterSeparator(); cw.WriteStartMethodInvoke("Tuple.Create"); cw.WriteLocationTaggedString(Prefix); cw.WriteParameterSeparator(); if (ValueGenerator != null) { cw.WriteStartMethodInvoke("Tuple.Create", "System.Object", "System.Int32"); context.ExpressionRenderingMode = ExpressionRenderingMode.InjectCode; } else { cw.WriteLocationTaggedString(Value); cw.WriteParameterSeparator(); // literal: true - This attribute value is a literal value cw.WriteBooleanLiteral(true); cw.WriteEndMethodInvoke(); // In VB, we need a line continuation cw.WriteLineContinuation(); } })); if (ValueGenerator != null) { ValueGenerator.Value.GenerateCode(target, context); context.FlushBufferedStatement(); context.ExpressionRenderingMode = oldMode; context.AddStatement(context.BuildCodeString(cw => { cw.WriteParameterSeparator(); cw.WriteSnippet(ValueGenerator.Location.AbsoluteIndex.ToString(CultureInfo.CurrentCulture)); cw.WriteEndMethodInvoke(); cw.WriteParameterSeparator(); // literal: false - This attribute value is not a literal value, it is dynamically generated cw.WriteBooleanLiteral(false); cw.WriteEndMethodInvoke(); // In VB, we need a line continuation cw.WriteLineContinuation(); })); } else { context.FlushBufferedStatement(); } }
/// <summary> /// Visits the current Razor parser span and looks for the model. /// </summary> /// <param name="span">The <see cref="Span"/> to visit.</param> public override void VisitSpan(Span span) { var modelSpan = span as ModelSpan; if(modelSpan == null) { return; } this.ModelTypeName = modelSpan.ModelTypeName; }
protected override PartialParseResult CanAcceptChange(Span target, TextChange normalizedChange) { if (((AutoCompleteAtEndOfSpan && IsAtEndOfSpan(target, normalizedChange)) || IsAtEndOfFirstLine(target, normalizedChange)) && normalizedChange.IsInsert && ParserHelpers.IsNewLine(normalizedChange.NewText) && AutoCompleteString != null) { return PartialParseResult.Rejected | PartialParseResult.AutoCompleteBlock; } return PartialParseResult.Rejected; }
internal void CalculateStart(Span prev) { if (prev == null) { Start = SourceLocation.Zero; } else { Start = new SourceLocationTracker(prev.Start).UpdateLocation(prev.Content).CurrentLocation; } }
public override void GenerateCode(Span target, CodeGeneratorContext context) { // Build the string string code = Prefix + target.Content + ";"; // Calculate the line pragma including information about where the user-specified code starts and ends (for editors) CodeLinePragma pragma = context.GenerateLinePragma(target, Prefix.Length, target.Content.Length); // Add the statement context.AddStatement(code, pragma); }
public override void VisitSpan(Span span) { base.VisitSpan(span); // Build linked list if (_previous != null) { _previous.Next = span; span.Previous = _previous; } _previous = span; CurrentBlock.Add(span); }
protected override PartialParseResult CanAcceptChange(Span target, TextChange normalizedChange) { if (AcceptedCharacters == AcceptedCharacters.Any) { return PartialParseResult.Rejected; } // In some editors intellisense insertions are handled as "dotless commits". If an intellisense selection is confirmed // via something like '.' a dotless commit will append a '.' and then insert the remaining intellisense selection prior // to the appended '.'. This 'if' statement attempts to accept the intermediate steps of a dotless commit via // intellisense. It will accept two cases: // 1. '@foo.' -> '@foobaz.'. // 2. '@foobaz..' -> '@foobaz.bar.'. Includes Sub-cases '@foobaz()..' -> '@foobaz().bar.' etc. // The key distinction being the double '.' in the second case. if (IsDotlessCommitInsertion(target, normalizedChange)) { return HandleDotlessCommitInsertion(target); } if (IsAcceptableReplace(target, normalizedChange)) { return HandleReplacement(target, normalizedChange); } int changeRelativePosition = normalizedChange.OldPosition - target.Start.AbsoluteIndex; // Get the edit context char? lastChar = null; if (changeRelativePosition > 0 && target.Content.Length > 0) { lastChar = target.Content[changeRelativePosition - 1]; } // Don't support 0->1 length edits if (lastChar == null) { return PartialParseResult.Rejected; } // Accepts cases when insertions are made at the end of a span or '.' is inserted within a span. if (IsAcceptableInsertion(target, normalizedChange)) { // Handle the insertion return HandleInsertion(target, lastChar.Value, normalizedChange); } if (IsAcceptableDeletion(target, normalizedChange)) { return HandleDeletion(target, lastChar.Value, normalizedChange); } return PartialParseResult.Rejected; }
public override void GenerateCode(Span target, CodeGeneratorContext context) { string generatedCode = context.BuildCodeString(cw => { cw.WriteSnippet(target.Content); }); context.GeneratedClass.Members.Add( new CodeSnippetTypeMember(Pad(generatedCode, target)) { LinePragma = context.GenerateLinePragma(target, target.Start.CharacterIndex) }); }
public override void VisitSpan(Span span) { Console.WriteLine("Span.Kind: " + span.Kind); Console.WriteLine("Span.GetType(): " + span.GetType().Name); Console.WriteLine("Span.Content: '" + span.Content + "'"); if (foundModelTypeName) return; if (IsModelSpan(span)) { VisitModelNameSpan(span.Next); } }
public void ParseModelKeyword_HandlesSingleInstance() { // Arrange + Act var document = "@ModelType Foo"; var spans = ParseDocument(document); // Assert var expectedSpans = new Span[] { new TransitionSpan(new SourceLocation(0, 0, 0), "@") { AcceptedCharacters = AcceptedCharacters.None }, new MetaCodeSpan(new SourceLocation(1, 0, 1), "ModelType ") { AcceptedCharacters = AcceptedCharacters.None }, new ModelSpan(new SourceLocation(11, 0, 11), " Foo", "Foo"), }; CollectionAssert.AreEqual(expectedSpans, spans); }
public System.Web.Razor.Parser.SyntaxTree.Span LocateOwner(Block root, TextChange change, Stack <Block> parentChain) { System.Web.Razor.Parser.SyntaxTree.Span span = null; parentChain.Push(root); foreach (SyntaxTreeNode current in root.Children) { if (current.Start.AbsoluteIndex > change.OldPosition) { break; } if (current.Start.AbsoluteIndex + current.Length >= change.OldPosition) { if (current.IsBlock) { Block block = current as Block; if (current.Start.AbsoluteIndex + current.Length == change.OldPosition) { System.Web.Razor.Parser.SyntaxTree.Span span2 = block.FindLastDescendentSpan(); if (span2.EditHandler.OwnsChange(span2, change)) { span = span2; break; } } else { span = LocateOwner(block, change, parentChain); if (span != null) { break; } } } else { System.Web.Razor.Parser.SyntaxTree.Span span3 = current as System.Web.Razor.Parser.SyntaxTree.Span; if (span3.EditHandler.OwnsChange(span3, change)) { span = span3; break; } } } } return(span); }