Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
<PackageReference Update="MSTest.TestAdapter" Version="3.3.1" />
<PackageReference Update="MSTest.TestFramework" Version="3.3.1" />
<PackageReference Update="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Update="coverlet.collector" Version="6.0.0" />
</ItemGroup>
</Project>
</Project>
33 changes: 33 additions & 0 deletions SqlScriptDom/ScriptDom/SqlServer/ColumnAliasStyle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//------------------------------------------------------------------------------
// <copyright file="ColumnAliasStyle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.SqlServer.TransactSql.ScriptDom
{
/// <summary>
/// Represents the possible ways of rendering column aliases in SELECT projections
/// </summary>
public enum ColumnAliasStyle
{
/// <summary>
/// Render column aliases using the AS keyword: expression AS alias
/// </summary>
AsKeyword,

/// <summary>
/// Render column aliases using the equals sign: alias = expression
/// </summary>
EqualsSign,

/// <summary>
/// Preserve the column alias style from the original script without converting between styles
/// </summary>
Preserve
}
}
28 changes: 28 additions & 0 deletions SqlScriptDom/ScriptDom/SqlServer/CommaPlacement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
// <copyright file="CommaPlacement.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;

namespace Microsoft.SqlServer.TransactSql.ScriptDom
{
/// <summary>
/// Represents the placement of commas when a comma-separated list is written on multiple lines.
/// </summary>
public enum CommaPlacement
{
/// <summary>
/// The comma is placed at the end of the line, after the item that precedes it.
/// </summary>
Trailing,

/// <summary>
/// The comma is placed at the start of the line, before the item that follows it.
/// When this value is used, the <see cref="IndentationMode"/> setting is ignored and
/// indentation always uses spaces.
/// </summary>
Leading
}
}
40 changes: 40 additions & 0 deletions SqlScriptDom/ScriptDom/SqlServer/IdentifierBracketing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
// <copyright file="IdentifierBracketing.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.SqlServer.TransactSql.ScriptDom
{
/// <summary>
/// Represents the possible ways of controlling square bracket usage around object
/// identifiers during script generation.
/// </summary>
public enum IdentifierBracketing
{
/// <summary>
/// Preserve the original bracketing/quoting of identifiers
/// </summary>
Preserve,

/// <summary>
/// Wrap all object identifiers in square brackets
/// </summary>
IncludeBrackets,

/// <summary>
/// Remove brackets from identifiers that do not require them. Identifiers that
/// conflict with reserved words or contain special characters retain their brackets.
/// This is a best-effort transformation: in rare cases an identifier lexes as an ordinary
/// identifier yet its brackets are semantically required by the surrounding syntax (for
/// example a schema-qualified name that collides with a special relational operator such as
/// AI_GENERATE_CHUNKS). Such brackets may be removed, so ExcludeBrackets is not guaranteed to
/// preserve semantics for every possible input.
/// </summary>
ExcludeBrackets
}
}
39 changes: 39 additions & 0 deletions SqlScriptDom/ScriptDom/SqlServer/IdentifierCasing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//------------------------------------------------------------------------------
// <copyright file="IdentifierCasing.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.SqlServer.TransactSql.ScriptDom
{
/// <summary>
/// Represents the possible ways of casing object identifiers during script generation.
/// This does not apply to keywords, string literals, function names, or variables.
/// </summary>
public enum IdentifierCasing
{
/// <summary>
/// Preserve the original casing of identifiers
/// </summary>
Preserve,

/// <summary>
/// All letters in upper case
/// </summary>
Uppercase,

/// <summary>
/// All letters in lower case
/// </summary>
Lowercase,

/// <summary>
/// First letter of the identifier capitalized, all remaining letters lower case
/// </summary>
PascalCase
}
}
33 changes: 33 additions & 0 deletions SqlScriptDom/ScriptDom/SqlServer/IndentationMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//------------------------------------------------------------------------------
// <copyright file="IndentationMode.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;

namespace Microsoft.SqlServer.TransactSql.ScriptDom
{
/// <summary>
/// Represents the character used to indent generated script.
/// </summary>
public enum IndentationMode
{
/// <summary>
/// Each indentation level inserts IndentationSize space characters.
/// </summary>
Spaces,

/// <summary>
/// Leading whitespace and the aligned gaps between tokens (for example a clause keyword and its
/// body, or column-definition fields) are written using only tab characters, rounding each
/// aligned column up to the next tab stop. Because those tab stops assume each tab is
/// <see cref="SqlScriptGeneratorOptions.IndentationSize"/> columns wide, the output only appears
/// aligned when the viewer's tab width (for example the editor's tab size) is set to the same
/// value as <see cref="SqlScriptGeneratorOptions.IndentationSize"/>. This mode is ignored
/// (indentation uses spaces) when <see cref="SqlScriptGeneratorOptions.CommaPlacement"/> is
/// <see cref="CommaPlacement.Leading"/>.
/// </summary>
Tabs
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,39 @@ public static string GetCasedString(string str, KeywordCasing casing)
return String.Empty;
}

/// <summary>
/// Retrieves a version of the specified identifier string, in the identifier casing format specified.
/// </summary>
/// <param name="str">The identifier string to get a specially cased version of</param>
/// <param name="casing">The identifier casing method to use</param>
/// <returns>A version of the string in the casing format specified in <paramref name="casing"/></returns>
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
public static string GetCasedString(string str, IdentifierCasing casing)
{
// Empty (or null) values are returned unchanged: there is nothing to recase, and PascalCase
// would otherwise index str[0] and throw during script generation.
if (string.IsNullOrEmpty(str))
{
return str;
}

switch (casing)
{
case IdentifierCasing.Preserve:
return str;
case IdentifierCasing.Lowercase:
return str.ToLowerInvariant();
case IdentifierCasing.Uppercase:
return str.ToUpperInvariant();
case IdentifierCasing.PascalCase:
return GetPascalCase(str);
default:
Debug.Fail("Invalid IdentifierCasing value");
break;
}
return str;
}

/// <summary>
/// Retrieves a Pascal Cased version of the string
/// </summary>
Expand Down Expand Up @@ -190,6 +223,21 @@ public static TSqlParserToken CreateWhitespaceToken(Int32 count)
return new TSqlParserToken(TSqlTokenType.WhiteSpace, ws);
}

/// <summary>
/// Create a whitespace token consisting of tab characters (used for indentation when
/// <see cref="SqlScriptGeneratorOptions.IndentationMode"/> is <see cref="IndentationMode.Tabs"/>).
/// </summary>
/// <param name="count">number of tab characters</param>
/// <returns></returns>
public static TSqlParserToken CreateTabToken(Int32 count)
{
// Build the tab whitespace
String ws = new String('\t', count);

// Create a whitespace token and add it to the layout table
return new TSqlParserToken(TSqlTokenType.WhiteSpace, ws);
}

internal static void CheckForNullReference(object variable, string variableName)
{
if (variableName == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ public AlignmentPointData(String name)
public Int32 Offset { get; set; }
public String Name { get; private set; }

// Tab-layout data (only used when IndentationMode is Tabs). TabTarget is the column the
// content following this alignment point is snapped to (a tab stop); TabShift is how far
// that content is shifted right versus the space layout; MaxLeftTabShift accumulates the
// TabShift of this point's left neighbours; and AbsorbsSeparator is set when this point is
// immediately followed by a single separator space that the tab run replaces.
public Int32 TabTarget { get; set; }
public Int32 TabShift { get; set; }
public Int32 MaxLeftTabShift { get; set; }
public Boolean AbsorbsSeparator { get; set; }

public void AddLeftPoint(AlignmentPointData ap, Int32 width)
{
Int32 currentWidth;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//------------------------------------------------------------------------------
// <copyright file="ScriptWriter.RightAlignedSeparatorElement.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System.Collections.Generic;

namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator
{
internal partial class ScriptWriter
{
/// <summary>
/// A run of tokens (e.g. a leading comma and a space) that must be right-aligned so
/// that it ends exactly at the offset of the alignment point that immediately follows
/// it. This is used for leading comma placement, where the comma should sit just before
/// the aligned item column rather than at the start of the line.
/// </summary>
internal class RightAlignedSeparatorElement : ScriptWriterElement
{
private readonly List<TSqlParserToken> _tokens;
private readonly int _width;

public RightAlignedSeparatorElement(List<TSqlParserToken> tokens)
{
_tokens = tokens;
_width = 0;
foreach (TSqlParserToken token in tokens)
{
if (token != null && token.Text != null)
{
_width += token.Text.Length;
}
}

this.ElementType = ScriptWriterElementType.RightAlignedSeparator;
}

public List<TSqlParserToken> Tokens
{
get { return _tokens; }
}

public int Width
{
get { return _width; }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal enum ScriptWriterElementType
AlignmentPoint,
Token,
NewLine,
RightAlignedSeparator,
}
}
}
Loading
Loading