Add support for interface members

This commit is contained in:
Dustin Campbell 2017-01-04 11:03:39 -08:00
Родитель 8814cf6b57
Коммит 1ad05ee587
7 изменённых файлов: 228 добавлений и 6 удалений

Просмотреть файл

@ -61,6 +61,9 @@
},
{
"include": "#struct-declaration"
},
{
"include": "#punctuation-semicolon"
}
]
},
@ -144,6 +147,25 @@
}
]
},
"interface-members": {
"patterns": [
{
"include": "#event-declaration"
},
{
"include": "#property-declaration"
},
{
"include": "#indexer-declaration"
},
{
"include": "#method-declaration"
},
{
"include": "#punctuation-semicolon"
}
]
},
"statement": {
"patterns": [
{
@ -663,7 +685,7 @@
},
"patterns": [
{
"include": "#punctuation-semicolon"
"include": "#interface-members"
}
]
}
@ -1098,14 +1120,14 @@
]
},
"method-declaration": {
"begin": "(?=(?<storage-modifiers>(?:\\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\\b\\s*)*)\\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<type-name>)(?:\\s*,\\s*\\g<type-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<type-name>)*)|(?:\\s*\\(\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)\\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<interface-name>)(?:\\s*,\\s*\\g<interface-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<interface-name>)*)|(?:\\s*\\(\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)(\\s*\\.\\s*))?(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\\s*<\\s*\\g<identifier>(?:\\s*,\\s*\\g<identifier>)*\\s*>\\s*)?\\s*(?:\\())",
"begin": "(?=(?<storage-modifiers>(?:\\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\\b\\s*)*)\\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<type-name>)(?:\\s*,\\s*\\g<type-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<type-name>)*)|(?:\\s*\\(\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)\\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<interface-name>)(?:\\s*,\\s*\\g<interface-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<interface-name>)*)|(?:\\s*\\(\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)(\\s*\\.\\s*))?(?<method-name>(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\\s*<\\s*\\g<identifier>(?:\\s*,\\s*\\g<identifier>)*\\s*>\\s*)?)\\s*(?:\\())",
"end": "(?=\\}|;)",
"patterns": [
{
"include": "#comment"
},
{
"match": "(?<storage-modifiers>(?:\\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\\b\\s*)*)\\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<type-name>)(?:\\s*,\\s*\\g<type-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<type-name>)*)|(?:\\s*\\(\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)\\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<interface-name>)(?:\\s*,\\s*\\g<interface-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<interface-name>)*)|(?:\\s*\\(\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)(\\s*\\.\\s*))?(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\\s*<\\s*\\g<identifier>(?:\\s*,\\s*\\g<identifier>)*\\s*>\\s*)?\\s*(?=\\()",
"match": "(?<storage-modifiers>(?:\\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\\b\\s*)*)\\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<type-name>)(?:\\s*,\\s*\\g<type-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<type-name>)*)|(?:\\s*\\(\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<type-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)\\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\\s*\\:\\:\\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\\s*<\\s*(?:\\g<interface-name>)(?:\\s*,\\s*\\g<interface-name>)*\\s*>\\s*)?(?:(?:\\*)*)?(?:(?:\\[,*\\])*)?(?:\\s*\\.\\s*\\g<interface-name>)*)|(?:\\s*\\(\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\\s*,\\s*(?:\\g<interface-name>)(?:\\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\\s*\\)\\s*))(?:(?:\\[,*\\])*)?)(\\s*\\.\\s*))?(?<method-name>(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\\s*<\\s*\\g<identifier>(?:\\s*,\\s*\\g<identifier>)*\\s*>\\s*)?)\\s*(?=\\()",
"captures": {
"1": {
"patterns": [
@ -1148,6 +1170,9 @@
{
"include": "#parenthesized-parameter-list"
},
{
"include": "#generic-constraints"
},
{
"include": "#expression-body"
},

Просмотреть файл

@ -1,7 +1,6 @@
## TODO List:
* Declarations:
* Interface members
* Constructor initializers
* Statements/Expressions:
@ -117,13 +116,13 @@ if you consider that regular expressions don't know that "class" is a keyword. T
#### Method declarations
* Expression: `(?=(?<storage-modifiers>(?:\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\b\s*)*)\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\s*\:\:\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\s*\.\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\s*<\s*(?:\g<type-name>)(?:\s*,\s*\g<type-name>)*\s*>\s*)?(?:(?:\*)*)?(?:(?:\[,*\])*)?(?:\s*\.\s*\g<type-name>)*)|(?:\s*\(\s*(?:\g<type-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\s*,\s*(?:\g<type-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\s*\)\s*))(?:(?:\[,*\])*)?)\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\s*\:\:\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\s*\.\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\s*<\s*(?:\g<interface-name>)(?:\s*,\s*\g<interface-name>)*\s*>\s*)?(?:(?:\*)*)?(?:(?:\[,*\])*)?(?:\s*\.\s*\g<interface-name>)*)|(?:\s*\(\s*(?:\g<interface-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\s*,\s*(?:\g<interface-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\s*\)\s*))(?:(?:\[,*\])*)?)(\s*\.\s*))?(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\s*<\s*\g<identifier>(?:\s*,\s*\g<identifier>)*\s*>\s*)?\s*(?:\())`
* Expression: `(?=(?<storage-modifiers>(?:\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\b\s*)*)\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\s*\:\:\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\s*\.\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\s*<\s*(?:\g<type-name>)(?:\s*,\s*\g<type-name>)*\s*>\s*)?(?:(?:\*)*)?(?:(?:\[,*\])*)?(?:\s*\.\s*\g<type-name>)*)|(?:\s*\(\s*(?:\g<type-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\s*,\s*(?:\g<type-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\s*\)\s*))(?:(?:\[,*\])*)?)\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\s*\:\:\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\s*\.\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\s*<\s*(?:\g<interface-name>)(?:\s*,\s*\g<interface-name>)*\s*>\s*)?(?:(?:\*)*)?(?:(?:\[,*\])*)?(?:\s*\.\s*\g<interface-name>)*)|(?:\s*\(\s*(?:\g<interface-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\s*,\s*(?:\g<interface-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\s*\)\s*))(?:(?:\[,*\])*)?)(\s*\.\s*))?(?<method-name>(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\s*<\s*\g<identifier>(?:\s*,\s*\g<identifier>)*\s*>\s*)?)\s*(?:\())`
* Break down:
* Storage modifiers: `(?<storage-modifiers>(?:\b(?:new|public|protected|internal|private|static|virtual|sealed|override|abstract|extern|async|partial)\b\s*)*)`
* Type name: `\s*(?<type-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\s*\:\:\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\s*\.\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\s*<\s*(?:\g<type-name>)(?:\s*,\s*\g<type-name>)*\s*>\s*)?(?:(?:\*)*)?(?:(?:\[,*\])*)?(?:\s*\.\s*\g<type-name>)*)|(?:\s*\(\s*(?:\g<type-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\s*,\s*(?:\g<type-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\s*\)\s*))(?:(?:\[,*\])*)?)`
* Interface name: `\s+(?:(?<interface-name>(?:(?:[_$[:alpha:]][_$[:alnum:]]*\s*\:\:\s*)?(?:(?:[_$[:alpha:]][_$[:alnum:]]*(?:\s*\.\s*[_$[:alpha:]][_$[:alnum:]]*)*)(?:\s*<\s*(?:\g<interface-name>)(?:\s*,\s*\g<interface-name>)*\s*>\s*)?(?:(?:\*)*)?(?:(?:\[,*\])*)?(?:\s*\.\s*\g<interface-name>)*)|(?:\s*\(\s*(?:\g<interface-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?(?:\s*,\s*(?:\g<interface-name>)(?:\s+[_$[:alpha:]][_$[:alnum:]]*)?)*\s*\)\s*))(?:(?:\[,*\])*)?)(\s*\.\s*))?`
* Method name and type parameters: `(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\s*<\s*\g<identifier>(?:\s*,\s*\g<identifier>)*\s*>\s*)?`
* Method name and type parameters: `(?<method-name>(?<identifier>[_$[:alpha:]][_$[:alnum:]]*)(?:\s*<\s*\g<identifier>(?:\s*,\s*\g<identifier>)*\s*>\s*)?)`
* End: `\s*(?:\()`
#### Constructor declarations

Просмотреть файл

@ -125,5 +125,17 @@ public event Type Event
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
it("declaration in interface", () => {
const input = Input.InInterface(`event EventHandler Event;`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Keywords.Event,
Token.Type("EventHandler"),
Token.Identifiers.EventName("Event"),
Token.Puncuation.Semicolon]);
});
});
});

Просмотреть файл

@ -60,5 +60,61 @@ public string this[int index]
Token.Puncuation.CloseBracket,
Token.Puncuation.Semicolon]);
});
it("declaration in interface", () => {
const input = Input.InInterface(`string this[int index] { get; set; }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Keywords.This,
Token.Puncuation.OpenBracket,
Token.Type("int"),
Token.Variables.Parameter("index"),
Token.Puncuation.CloseBracket,
Token.Puncuation.OpenBrace,
Token.Keywords.Get,
Token.Puncuation.Semicolon,
Token.Keywords.Set,
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
it("declaration in interface (read-only)", () => {
const input = Input.InInterface(`string this[int index] { get; }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Keywords.This,
Token.Puncuation.OpenBracket,
Token.Type("int"),
Token.Variables.Parameter("index"),
Token.Puncuation.CloseBracket,
Token.Puncuation.OpenBrace,
Token.Keywords.Get,
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
it("declaration in interface (write-only)", () => {
const input = Input.InInterface(`string this[int index] { set; }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Keywords.This,
Token.Puncuation.OpenBracket,
Token.Type("int"),
Token.Variables.Parameter("index"),
Token.Puncuation.CloseBracket,
Token.Puncuation.OpenBrace,
Token.Keywords.Set,
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
});
});

Просмотреть файл

@ -52,6 +52,26 @@ int Add(int x, int y)
Token.Puncuation.CloseBrace]);
});
it("declaration in with generic constraints", () => {
const input = Input.InClass(`TResult GetString<T, TResult>(T arg) where T : TResult { }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("TResult"),
Token.Identifiers.MethodName("GetString<T, TResult>"),
Token.Puncuation.OpenParen,
Token.Type("T"),
Token.Variables.Parameter("arg"),
Token.Puncuation.CloseParen,
Token.Keywords.Where,
Token.Type("T"),
Token.Puncuation.Colon,
Token.Type("TResult"),
Token.Puncuation.OpenBrace,
Token.Puncuation.CloseBrace]);
});
it("expression body", () => {
const input = Input.InClass(`int Add(int x, int y) => x + y;`);
@ -91,5 +111,58 @@ int Add(int x, int y)
Token.Puncuation.CloseParen,
Token.Puncuation.Semicolon]);
});
it("declaration in interface", () => {
const input = Input.InInterface(`string GetString();`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Identifiers.MethodName("GetString"),
Token.Puncuation.OpenParen,
Token.Puncuation.CloseParen,
Token.Puncuation.Semicolon]);
});
it("declaration in interface with parameters", () => {
const input = Input.InInterface(`string GetString(string format, params object[] args);`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Identifiers.MethodName("GetString"),
Token.Puncuation.OpenParen,
Token.Type("string"),
Token.Variables.Parameter("format"),
Token.Puncuation.Comma,
Token.Keywords.Modifiers.Params,
Token.Type("object"),
Token.Puncuation.OpenBracket,
Token.Puncuation.CloseBracket,
Token.Variables.Parameter("args"),
Token.Puncuation.CloseParen,
Token.Puncuation.Semicolon]);
});
it("declaration in interface with generic constraints", () => {
const input = Input.InInterface(`TResult GetString<T, TResult>(T arg) where T : TResult;`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("TResult"),
Token.Identifiers.MethodName("GetString<T, TResult>"),
Token.Puncuation.OpenParen,
Token.Type("T"),
Token.Variables.Parameter("arg"),
Token.Puncuation.CloseParen,
Token.Keywords.Where,
Token.Type("T"),
Token.Puncuation.Colon,
Token.Type("TResult"),
Token.Puncuation.Semicolon]);
});
});
});

Просмотреть файл

@ -254,5 +254,49 @@ private bool prop2 => true;`);
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
it("declaration in interface", () => {
const input = Input.InInterface(`string Bar { get; set; }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Identifiers.PropertyName("Bar"),
Token.Puncuation.OpenBrace,
Token.Keywords.Get,
Token.Puncuation.Semicolon,
Token.Keywords.Set,
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
it("declaration in interface (read-only)", () => {
const input = Input.InInterface(`string Bar { get; }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Identifiers.PropertyName("Bar"),
Token.Puncuation.OpenBrace,
Token.Keywords.Get,
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
it("declaration in interface (write-only)", () => {
const input = Input.InInterface(`string Bar { set; }`);
const tokens = tokenize(input);
tokens.should.deep.equal([
Token.Type("string"),
Token.Identifiers.PropertyName("Bar"),
Token.Puncuation.OpenBrace,
Token.Keywords.Set,
Token.Puncuation.Semicolon,
Token.Puncuation.CloseBrace]);
});
});
});

Просмотреть файл

@ -78,6 +78,19 @@ class TestClass {
return new Input(lines, { startLine: 2, startIndex: 4, endLine: lines.length - 1, endIndex: 0 });
}
public static InInterface(input: string) {
let text = `
interface TestInterface {
${input}
}`;
// ensure consistent line-endings irrelevant of OS
text = text.replace('\r\n', '\n');
let lines = text.split('\n');
return new Input(lines, { startLine: 2, startIndex: 4, endLine: lines.length - 1, endIndex: 0 });
}
public static InMethod(input: string) {
let text = `
class TestClass {