// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php
using Nova.Parsing;
using Nova.Rendering;
namespace Nova.CodeDOM
{
/// <summary>
/// Represents a stand-alone block of code restricted to a local scope (surrounded by braces).
/// </summary>
public class BlockDecl : BlockStatement
{
#region /* CONSTRUCTORS */
/// <summary>
/// Create a <see cref="BlockDecl"/>.
/// </summary>
public BlockDecl(CodeObject body)
: base(body, false)
{ }
/// <summary>
/// Create a <see cref="BlockDecl"/>.
/// </summary>
public BlockDecl()
: base(null, false)
{ }
/// <summary>
/// Create a <see cref="BlockDecl"/> with the specified <see cref="CodeObject"/>s in the body.
/// </summary>
public BlockDecl(params CodeObject[] codeObjects)
: base(codeObjects)
{ }
#endregion
#region /* PROPERTIES */
/// <summary>
/// Always <c>false</c>.
/// </summary>
public override bool HasHeader
{
get { return false; }
}
#endregion
#region /* METHODS */
/// <summary>
/// Attach an <see cref="Annotation"/> (<see cref="Comment"/>, <see cref="DocComment"/>, <see cref="Attribute"/>, <see cref="CompilerDirective"/>, or <see cref="Message"/>) to the <see cref="CodeObject"/>.
/// </summary>
/// <param name="annotation">The <see cref="Annotation"/>.</param>
/// <param name="atFront">Inserts at the front if true, otherwise adds at the end.</param>
public override void AttachAnnotation(Annotation annotation, bool atFront)
{
// Don't allow EOL comments on a BlockDecl since it has nothing to display them on - move
// them to the child Block so that they can be displayed.
if (annotation.IsEOL)
Body.AttachAnnotation(annotation, atFront);
else
base.AttachAnnotation(annotation, atFront);
}
#endregion
#region /* PARSING */
internal static void AddParsePoints()
{
// Use a parse-priority of 300 (GenericMethodDecl uses 0, UnresolvedRef uses 100, PropertyDeclBase uses 200, Initializer uses 400)
Parser.AddParsePoint(Block.ParseTokenStart, 300, Parse, typeof(IBlock));
}
/// <summary>
/// Parse a <see cref="BlockDecl"/>.
/// </summary>
public static BlockDecl Parse(Parser parser, CodeObject parent, ParseFlags flags)
{
return new BlockDecl(parser, parent);
}
/// <summary>
/// Parse a <see cref="BlockDecl"/>.
/// </summary>
public BlockDecl(Parser parser, CodeObject parent, params string[] terminators)
: base(parser, parent)
{
new Block(out _body, parser, this, true, terminators); // Parse the body
}
#endregion
#region /* FORMATTING */
/// <summary>
/// True if the <see cref="Statement"/> has parens around its argument.
/// </summary>
public override bool HasArgumentParens
{
get { return false; }
}
/// <summary>
/// Reformat the <see cref="Block"/> body.
/// </summary>
public override void ReformatBlock()
{
// BlockDecls must always have braces and start on a new line, and default to the ending
// brace being on a new line without any preceeding blank lines.
_body.HasBraces = true;
_body.IsFirstOnLine = true;
_body.SetNewLines(1);
}
#endregion
#region /* RENDERING */
public override void AsText(CodeWriter writer, RenderFlags flags)
{
if (flags.HasFlag(RenderFlags.Description))
TypeRefBase.AsTextType(writer, GetType(), RenderFlags.None);
else
base.AsText(writer, flags);
}
protected override void AsTextStatement(CodeWriter writer, RenderFlags flags)
{
UpdateLineCol(writer, flags);
}
protected override void AsTextAfter(CodeWriter writer, RenderFlags flags)
{
base.AsTextAfter(writer, flags | RenderFlags.SuppressNewLine);
}
#endregion
}
}