diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs
index df5ea3c9..f23a57b0 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs
@@ -332,7 +332,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
///
/// Gets a static instance of an empty completion list to avoid
- // unneeded memory allocations
+ /// unneeded memory allocations
///
internal static CompletionItem[] EmptyCompletionList
{
@@ -342,6 +342,16 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
}
}
+ ///
+ /// Checks whether a given word is in the reserved
+ /// word list or not
+ ///
+ internal static bool IsReservedWord(string text)
+ {
+ int pos = Array.IndexOf(DefaultCompletionText, text.ToLower());
+ return pos > -1;
+ }
+
///
/// Gets or sets the current workspace service instance
/// Setter for internal testing purposes only
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/SqlCompletionItem.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/SqlCompletionItem.cs
index 39247f34..49e3fd44 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/SqlCompletionItem.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Completion/SqlCompletionItem.cs
@@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+using System;
using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Management.SqlParser.Intellisense;
@@ -45,7 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
{
InsertText = GetCompletionItemInsertName();
Label = DeclarationTitle;
- if (StartsWithBracket(TokenText))
+ if (StartsWithBracket(TokenText) || AutoCompleteHelper.IsReservedWord(InsertText))
{
Label = WithBracket(Label);
InsertText = WithBracket(InsertText);
@@ -142,7 +143,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
int row,
int startColumn,
int endColumn)
- {
+ {
CompletionItem item = new CompletionItem()
{
Label = label,
diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/SqlCompletionItemTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/SqlCompletionItemTests.cs
index 727e379d..a1030578 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/SqlCompletionItemTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/SqlCompletionItemTests.cs
@@ -13,6 +13,304 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer
{
public class SqlCompletionItemTests
{
+ private static readonly string[] ReservedWords = new string[]
+ {
+ "all",
+ "alter",
+ "and",
+ "apply",
+ "as",
+ "asc",
+ "at",
+ "backup",
+ "begin",
+ "binary",
+ "bit",
+ "break",
+ "bulk",
+ "by",
+ "call",
+ "cascade",
+ "case",
+ "catch",
+ "char",
+ "character",
+ "check",
+ "checkpoint",
+ "close",
+ "clustered",
+ "column",
+ "columnstore",
+ "commit",
+ "connect",
+ "constraint",
+ "continue",
+ "create",
+ "cross",
+ "current_date",
+ "cursor",
+ "cursor_close_on_commit",
+ "cursor_default",
+ "data",
+ "data_compression",
+ "database",
+ "date",
+ "datetime",
+ "datetime2",
+ "days",
+ "dbcc",
+ "dec",
+ "decimal",
+ "declare",
+ "default",
+ "delete",
+ "deny",
+ "desc",
+ "description",
+ "disabled",
+ "disk",
+ "distinct",
+ "double",
+ "drop",
+ "drop_existing",
+ "dump",
+ "dynamic",
+ "else",
+ "enable",
+ "encrypted",
+ "end",
+ "end-exec",
+ "exec",
+ "execute",
+ "exists",
+ "exit",
+ "external",
+ "fast_forward",
+ "fetch",
+ "file",
+ "filegroup",
+ "filename",
+ "filestream",
+ "filter",
+ "first",
+ "float",
+ "for",
+ "foreign",
+ "from",
+ "full",
+ "function",
+ "geography",
+ "get",
+ "global",
+ "go",
+ "goto",
+ "grant",
+ "group",
+ "hash",
+ "hashed",
+ "having",
+ "hidden",
+ "hierarchyid",
+ "holdlock",
+ "hours",
+ "identity",
+ "identitycol",
+ "if",
+ "image",
+ "immediate",
+ "include",
+ "index",
+ "inner",
+ "insert",
+ "instead",
+ "int",
+ "integer",
+ "intersect",
+ "into",
+ "isolation",
+ "join",
+ "json",
+ "key",
+ "language",
+ "last",
+ "left",
+ "level",
+ "lineno",
+ "load",
+ "local",
+ "locate",
+ "location",
+ "login",
+ "masked",
+ "maxdop",
+ "merge",
+ "message",
+ "modify",
+ "move",
+ "namespace",
+ "native_compilation",
+ "nchar",
+ "next",
+ "no",
+ "nocheck",
+ "nocount",
+ "nonclustered",
+ "none",
+ "norecompute",
+ "not",
+ "now",
+ "null",
+ "numeric",
+ "object",
+ "of",
+ "off",
+ "offsets",
+ "on",
+ "online",
+ "open",
+ "openrowset",
+ "openxml",
+ "option",
+ "or",
+ "order",
+ "out",
+ "outer",
+ "output",
+ "over",
+ "owner",
+ "partial",
+ "partition",
+ "password",
+ "path",
+ "percent",
+ "percentage",
+ "period",
+ "persisted",
+ "plan",
+ "policy",
+ "precision",
+ "predicate",
+ "primary",
+ "print",
+ "prior",
+ "proc",
+ "procedure",
+ "public",
+ "query_store",
+ "quoted_identifier",
+ "raiserror",
+ "range",
+ "raw",
+ "read",
+ "read_committed_snapshot",
+ "read_only",
+ "read_write",
+ "readonly",
+ "readtext",
+ "real",
+ "rebuild",
+ "receive",
+ "reconfigure",
+ "recovery",
+ "recursive",
+ "recursive_triggers",
+ "references",
+ "relative",
+ "remove",
+ "reorganize",
+ "required",
+ "restart",
+ "restore",
+ "restrict",
+ "resume",
+ "return",
+ "returns",
+ "revert",
+ "revoke",
+ "rollback",
+ "rollup",
+ "row",
+ "rowcount",
+ "rowguidcol",
+ "rows",
+ "rule",
+ "sample",
+ "save",
+ "schema",
+ "schemabinding",
+ "scoped",
+ "scroll",
+ "secondary",
+ "security",
+ "select",
+ "send",
+ "sent",
+ "sequence",
+ "server",
+ "session",
+ "set",
+ "sets",
+ "setuser",
+ "simple",
+ "smallint",
+ "smallmoney",
+ "snapshot",
+ "sql",
+ "standard",
+ "start",
+ "started",
+ "state",
+ "statement",
+ "static",
+ "statistics",
+ "statistics_norecompute",
+ "status",
+ "stopped",
+ "sysname",
+ "system",
+ "system_time",
+ "table",
+ "take",
+ "target",
+ "then",
+ "throw",
+ "time",
+ "timestamp",
+ "tinyint",
+ "to",
+ "top",
+ "tran",
+ "transaction",
+ "trigger",
+ "truncate",
+ "try",
+ "tsql",
+ "type",
+ "uncommitted",
+ "union",
+ "unique",
+ "uniqueidentifier",
+ "updatetext",
+ "use",
+ "user",
+ "using",
+ "value",
+ "values",
+ "varchar",
+ "version",
+ "view",
+ "waitfor",
+ "when",
+ "where",
+ "while",
+ "with",
+ "within",
+ "without",
+ "writetext",
+ "xact_abort",
+ "xml",
+ };
+
[Fact]
public void InsertTextShouldIncludeBracketGivenNameWithSpace()
{
@@ -132,6 +430,24 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer
Assert.Equal(completionItem.Detail, expected);
}
+ [Fact]
+ public void LabelShouldIncBracketGivenReservedName()
+ {
+ foreach (string word in ReservedWords)
+ {
+ string declarationTitle = word;
+ string expected = "[" + declarationTitle + "]";
+ DeclarationType declarationType = DeclarationType.Table;
+ string tokenText = "[]";
+ SqlCompletionItem item = new SqlCompletionItem(declarationTitle, declarationType, tokenText);
+ CompletionItem completionItem = item.CreateCompletionItem(0, 1, 2);
+
+ Assert.Equal(completionItem.Label, expected);
+ Assert.Equal(completionItem.InsertText, expected);
+ Assert.Equal(completionItem.Detail, expected);
+ }
+ }
+
[Fact]
public void KindShouldBeModuleGivenSchemaDeclarationType()
{