diff --git a/grammars/csharp.tmLanguage b/grammars/csharp.tmLanguage
index 179c2bc..64df1f2 100644
--- a/grammars/csharp.tmLanguage
+++ b/grammars/csharp.tmLanguage
@@ -8620,6 +8620,10 @@
include
#preprocessor-pragma-checksum
+
+ include
+ #preprocessor-app-directive
+
preprocessor-define-or-undef
@@ -8950,6 +8954,198 @@
+ preprocessor-app-directive
+
+ begin
+ \s*(:)\s*
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.separator.colon.cs
+
+
+ end
+ (?=$)
+ patterns
+
+
+ include
+ #preprocessor-app-directive-package
+
+
+ include
+ #preprocessor-app-directive-property
+
+
+ include
+ #preprocessor-app-directive-project
+
+
+ include
+ #preprocessor-app-directive-sdk
+
+
+ include
+ #preprocessor-app-directive-generic
+
+
+
+ preprocessor-app-directive-package
+
+ match
+ \b(package)\b\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\s*
+ captures
+
+ 1
+
+ name
+ keyword.preprocessor.package.cs
+
+ 2
+
+ patterns
+
+
+ include
+ #preprocessor-app-directive-package-name
+
+
+
+ 3
+
+ name
+ punctuation.separator.at.cs
+
+ 4
+
+ name
+ string.unquoted.preprocessor.message.cs
+
+
+
+ preprocessor-app-directive-property
+
+ match
+ \b(property)\b\s*([_[:alpha:]][_[:alnum:]]*)?(=)?(.*)?\s*
+ captures
+
+ 1
+
+ name
+ keyword.preprocessor.property.cs
+
+ 2
+
+ name
+ entity.name.variable.preprocessor.symbol.cs
+
+ 3
+
+ name
+ punctuation.separator.equals.cs
+
+ 4
+
+ name
+ string.unquoted.preprocessor.message.cs
+
+
+
+ preprocessor-app-directive-project
+
+ match
+ \b(project)\b\s*(.*)?\s*
+ captures
+
+ 1
+
+ name
+ keyword.preprocessor.project.cs
+
+ 2
+
+ name
+ string.unquoted.preprocessor.message.cs
+
+
+
+ preprocessor-app-directive-sdk
+
+ match
+ \b(sdk)\b\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\s*
+ captures
+
+ 1
+
+ name
+ keyword.preprocessor.sdk.cs
+
+ 2
+
+ patterns
+
+
+ include
+ #preprocessor-app-directive-package-name
+
+
+
+ 3
+
+ name
+ punctuation.separator.at.cs
+
+ 4
+
+ name
+ string.unquoted.preprocessor.message.cs
+
+
+
+ preprocessor-app-directive-package-name
+
+ patterns
+
+
+ match
+ (\.)([_[:alpha:]][_[:alnum:]]*)
+ captures
+
+ 1
+
+ name
+ punctuation.dot.cs
+
+ 2
+
+ name
+ entity.name.variable.preprocessor.symbol.cs
+
+
+
+
+ name
+ entity.name.variable.preprocessor.symbol.cs
+ match
+ [_[:alpha:]][_[:alnum:]]*
+
+
+
+ preprocessor-app-directive-generic
+
+ match
+ \b(.*)?\s*
+ captures
+
+ 1
+
+ name
+ string.unquoted.preprocessor.message.cs
+
+
+
preprocessor-expression
patterns
diff --git a/grammars/csharp.tmLanguage.cson b/grammars/csharp.tmLanguage.cson
index 0be8ac1..7b1884c 100644
--- a/grammars/csharp.tmLanguage.cson
+++ b/grammars/csharp.tmLanguage.cson
@@ -5201,6 +5201,9 @@ repository:
{
include: "#preprocessor-pragma-checksum"
}
+ {
+ include: "#preprocessor-app-directive"
+ }
]
"preprocessor-define-or-undef":
match: "\\b(?:(define)|(undef))\\b\\s*\\b([_[:alpha:]][_[:alnum:]]*)\\b"
@@ -5347,6 +5350,97 @@ repository:
name: "string.quoted.double.cs"
"5":
name: "string.quoted.double.cs"
+ "preprocessor-app-directive":
+ begin: "\\s*(:)\\s*"
+ beginCaptures:
+ "1":
+ name: "punctuation.separator.colon.cs"
+ end: "(?=$)"
+ patterns: [
+ {
+ include: "#preprocessor-app-directive-package"
+ }
+ {
+ include: "#preprocessor-app-directive-property"
+ }
+ {
+ include: "#preprocessor-app-directive-project"
+ }
+ {
+ include: "#preprocessor-app-directive-sdk"
+ }
+ {
+ include: "#preprocessor-app-directive-generic"
+ }
+ ]
+ "preprocessor-app-directive-package":
+ match: "\\b(package)\\b\\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\\s*"
+ captures:
+ "1":
+ name: "keyword.preprocessor.package.cs"
+ "2":
+ patterns: [
+ {
+ include: "#preprocessor-app-directive-package-name"
+ }
+ ]
+ "3":
+ name: "punctuation.separator.at.cs"
+ "4":
+ name: "string.unquoted.preprocessor.message.cs"
+ "preprocessor-app-directive-property":
+ match: "\\b(property)\\b\\s*([_[:alpha:]][_[:alnum:]]*)?(=)?(.*)?\\s*"
+ captures:
+ "1":
+ name: "keyword.preprocessor.property.cs"
+ "2":
+ name: "entity.name.variable.preprocessor.symbol.cs"
+ "3":
+ name: "punctuation.separator.equals.cs"
+ "4":
+ name: "string.unquoted.preprocessor.message.cs"
+ "preprocessor-app-directive-project":
+ match: "\\b(project)\\b\\s*(.*)?\\s*"
+ captures:
+ "1":
+ name: "keyword.preprocessor.project.cs"
+ "2":
+ name: "string.unquoted.preprocessor.message.cs"
+ "preprocessor-app-directive-sdk":
+ match: "\\b(sdk)\\b\\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\\s*"
+ captures:
+ "1":
+ name: "keyword.preprocessor.sdk.cs"
+ "2":
+ patterns: [
+ {
+ include: "#preprocessor-app-directive-package-name"
+ }
+ ]
+ "3":
+ name: "punctuation.separator.at.cs"
+ "4":
+ name: "string.unquoted.preprocessor.message.cs"
+ "preprocessor-app-directive-package-name":
+ patterns: [
+ {
+ match: "(\\.)([_[:alpha:]][_[:alnum:]]*)"
+ captures:
+ "1":
+ name: "punctuation.dot.cs"
+ "2":
+ name: "entity.name.variable.preprocessor.symbol.cs"
+ }
+ {
+ name: "entity.name.variable.preprocessor.symbol.cs"
+ match: "[_[:alpha:]][_[:alnum:]]*"
+ }
+ ]
+ "preprocessor-app-directive-generic":
+ match: "\\b(.*)?\\s*"
+ captures:
+ "1":
+ name: "string.unquoted.preprocessor.message.cs"
"preprocessor-expression":
patterns: [
{
diff --git a/src/csharp.tmLanguage.yml b/src/csharp.tmLanguage.yml
index af7aab4..775c5aa 100644
--- a/src/csharp.tmLanguage.yml
+++ b/src/csharp.tmLanguage.yml
@@ -3388,6 +3388,7 @@ repository:
- include: '#preprocessor-line'
- include: '#preprocessor-pragma-warning'
- include: '#preprocessor-pragma-checksum'
+ - include: '#preprocessor-app-directive'
preprocessor-define-or-undef:
match: \b(?:(define)|(undef))\b\s*\b([_[:alpha:]][_[:alnum:]]*)\b
@@ -3490,6 +3491,66 @@ repository:
'4': { name: string.quoted.double.cs }
'5': { name: string.quoted.double.cs }
+ preprocessor-app-directive:
+ begin: \s*(:)\s*
+ beginCaptures:
+ '1': { name: punctuation.separator.colon.cs }
+ end: (?=$)
+ patterns:
+ - include: '#preprocessor-app-directive-package'
+ - include: '#preprocessor-app-directive-property'
+ - include: '#preprocessor-app-directive-project'
+ - include: '#preprocessor-app-directive-sdk'
+ - include: '#preprocessor-app-directive-generic'
+
+ preprocessor-app-directive-package:
+ match: \b(package)\b\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\s*
+ captures:
+ '1': { name: keyword.preprocessor.package.cs }
+ '2':
+ patterns:
+ - include: '#preprocessor-app-directive-package-name'
+ '3': { name: punctuation.separator.at.cs }
+ '4': { name: string.unquoted.preprocessor.message.cs }
+
+ preprocessor-app-directive-property:
+ match: \b(property)\b\s*([_[:alpha:]][_[:alnum:]]*)?(=)?(.*)?\s*
+ captures:
+ '1': { name: keyword.preprocessor.property.cs }
+ '2': { name: entity.name.variable.preprocessor.symbol.cs }
+ '3': { name: punctuation.separator.equals.cs }
+ '4': { name: string.unquoted.preprocessor.message.cs }
+
+ preprocessor-app-directive-project:
+ match: \b(project)\b\s*(.*)?\s*
+ captures:
+ '1': { name: keyword.preprocessor.project.cs }
+ '2': { name: string.unquoted.preprocessor.message.cs }
+
+ preprocessor-app-directive-sdk:
+ match: \b(sdk)\b\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\s*
+ captures:
+ '1': { name: keyword.preprocessor.sdk.cs }
+ '2':
+ patterns:
+ - include: '#preprocessor-app-directive-package-name'
+ '3': { name: punctuation.separator.at.cs }
+ '4': { name: string.unquoted.preprocessor.message.cs }
+
+ preprocessor-app-directive-package-name:
+ patterns:
+ - match: (\.)([_[:alpha:]][_[:alnum:]]*)
+ captures:
+ '1': { name: punctuation.dot.cs }
+ '2': { name: entity.name.variable.preprocessor.symbol.cs }
+ - name: entity.name.variable.preprocessor.symbol.cs
+ match: '[_[:alpha:]][_[:alnum:]]*'
+
+ preprocessor-app-directive-generic:
+ match: \b(.*)?\s*
+ captures:
+ '1': { name: string.unquoted.preprocessor.message.cs }
+
preprocessor-expression:
patterns:
- begin: \(
diff --git a/test/preprocessor.tests.ts b/test/preprocessor.tests.ts
index f6c6015..bf43e70 100644
--- a/test/preprocessor.tests.ts
+++ b/test/preprocessor.tests.ts
@@ -696,4 +696,169 @@ public ActionResult Register()
]);
});
});
+
+ describe("AppDirectives", () => {
+ it("#:package", async () => {
+ const input = `#:package`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Package,
+ ]);
+ });
+
+ it("#:package with name", async () => {
+ const input = `#:package Foo.Goo`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Package,
+ Token.Identifier.PreprocessorSymbol("Foo"),
+ Token.Punctuation.Dot,
+ Token.Identifier.PreprocessorSymbol("Goo"),
+ ]);
+ });
+
+ it("#:package with name and version", async () => {
+ const input = `#:package Foo.Goo@1.0.0`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Package,
+ Token.Identifier.PreprocessorSymbol("Foo"),
+ Token.Punctuation.Dot,
+ Token.Identifier.PreprocessorSymbol("Goo"),
+ Token.Punctuation.At,
+ Token.PreprocessorMessage("1.0.0"),
+ ]);
+ });
+
+ it("#:project", async () => {
+ const input = `#:project`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Project,
+ ]);
+ });
+
+ it("#:project with path", async () => {
+ const input = `#:project ./path/to/project`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Project,
+ Token.PreprocessorMessage("./path/to/project"),
+ ]);
+ });
+
+ it("#:property", async () => {
+ const input = `#:property`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Property,
+ ]);
+ });
+
+ it("#:property with name", async () => {
+ const input = `#:property Foo_Property`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Property,
+ Token.Identifier.PreprocessorSymbol("Foo_Property"),
+ ]);
+ });
+
+ it("#:property with name and value", async () => {
+ const input = `#:property Foo_Property=Some Value`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Property,
+ Token.Identifier.PreprocessorSymbol("Foo_Property"),
+ Token.Punctuation.Equals,
+ Token.PreprocessorMessage("Some Value"),
+ ]);
+ });
+
+ it("#:sdk", async () => {
+ const input = `#:sdk`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Sdk,
+ ]);
+ });
+
+ it("#:sdk with name", async () => {
+ const input = `#:sdk Foo.Sdk`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Sdk,
+ Token.Identifier.PreprocessorSymbol("Foo"),
+ Token.Punctuation.Dot,
+ Token.Identifier.PreprocessorSymbol("Sdk"),
+ ]);
+ });
+
+ it("#:sdk with name and version", async () => {
+ const input = `#:sdk Foo.Sdk@1.0.0`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.Keyword.Preprocessor.Sdk,
+ Token.Identifier.PreprocessorSymbol("Foo"),
+ Token.Punctuation.Dot,
+ Token.Identifier.PreprocessorSymbol("Sdk"),
+ Token.Punctuation.At,
+ Token.PreprocessorMessage("1.0.0"),
+ ]);
+ });
+
+ it("#:", async () => {
+ const input = `#:`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ ]);
+ });
+
+ it("#: with generic message", async () => {
+ const input = `#:this is a generic directive`;
+ const tokens = await tokenize(input);
+
+ tokens.should.deep.equal([
+ Token.Punctuation.Hash,
+ Token.Punctuation.Colon,
+ Token.PreprocessorMessage("this is a generic directive"),
+ ]);
+ });
+ });
});
\ No newline at end of file
diff --git a/test/utils/tokenize.ts b/test/utils/tokenize.ts
index 12beffd..e6cde77 100644
--- a/test/utils/tokenize.ts
+++ b/test/utils/tokenize.ts
@@ -376,13 +376,17 @@ export namespace Token {
export const Hidden = createToken('hidden', 'keyword.preprocessor.hidden.cs');
export const If = createToken('if', 'keyword.preprocessor.if.cs');
export const Line = createToken('line', 'keyword.preprocessor.line.cs');
+ export const Load = createToken('load', 'keyword.preprocessor.load.cs');
+ export const Package = createToken('package', 'keyword.preprocessor.package.cs');
export const Pragma = createToken('pragma', 'keyword.preprocessor.pragma.cs');
+ export const Property = createToken('property', 'keyword.preprocessor.property.cs');
+ export const Project = createToken('project', 'keyword.preprocessor.project.cs');
+ export const R = createToken('r', 'keyword.preprocessor.r.cs');
export const Region = createToken('region', 'keyword.preprocessor.region.cs');
export const Restore = createToken('restore', 'keyword.preprocessor.restore.cs');
+ export const Sdk = createToken('sdk', 'keyword.preprocessor.sdk.cs');
export const Undef = createToken('undef', 'keyword.preprocessor.undef.cs');
export const Warning = createToken('warning', 'keyword.preprocessor.warning.cs');
- export const R = createToken('r', 'keyword.preprocessor.r.cs');
- export const Load = createToken('load', 'keyword.preprocessor.load.cs');
}
export const AttributeSpecifier = (text: string) => createToken(text, 'keyword.other.attribute-specifier.cs');
@@ -591,12 +595,15 @@ export namespace Token {
export const Accessor = createToken('.', 'punctuation.accessor.cs');
export const AccessorPointer = createToken('->', 'punctuation.accessor.pointer.cs');
export const Asterisk = createToken('*', 'punctuation.separator.asterisk.cs')
+ export const At = createToken('@', 'punctuation.separator.at.cs');
export const CloseBrace = createToken('}', 'punctuation.curlybrace.close.cs');
export const CloseBracket = createToken(']', 'punctuation.squarebracket.close.cs');
export const CloseParen = createToken(')', 'punctuation.parenthesis.close.cs');
export const Colon = createToken(':', 'punctuation.separator.colon.cs');
export const ColonColon = createToken('::', 'punctuation.separator.coloncolon.cs');
+ export const Dot = createToken('.', 'punctuation.dot.cs');
export const Comma = createToken(',', 'punctuation.separator.comma.cs');
+ export const Equals = createToken('=', 'punctuation.separator.equals.cs');
export const Hash = createToken('#', 'punctuation.separator.hash.cs')
export const OpenBrace = createToken('{', 'punctuation.curlybrace.open.cs');
export const OpenBracket = createToken('[', 'punctuation.squarebracket.open.cs');