Resolve ptr, array & aa in types, add typeOf field
typeOf field is new tab-delimited field in dcd-client output, so you no longer need to manually guess types / parse code. Calltips still yield the actual written type, but in case of "auto", the typeOf column may contain more useful info.
This commit is contained in:
parent
690d6254db
commit
22f65d51fe
13
README.md
13
README.md
|
@ -175,13 +175,19 @@ a tab separated format:
|
||||||
* definition: function or variable definition string or close approximation for information display purpose
|
* definition: function or variable definition string or close approximation for information display purpose
|
||||||
* symbol location: in which file (or `stdin`) & byte offset this symbol is defined. Separated with a space.
|
* symbol location: in which file (or `stdin`) & byte offset this symbol is defined. Separated with a space.
|
||||||
* documentation: escaped documentation string of this symbol
|
* documentation: escaped documentation string of this symbol
|
||||||
|
* typeOf: resolved type name of this symbol:
|
||||||
|
<!-- the items in list are copied from messages.d -->
|
||||||
|
* For variables, fields, globals, constants: resolved type or empty if unresolved.
|
||||||
|
* For functions: resolved return type or empty if unresolved.
|
||||||
|
* For constructors: may be struct/class name or empty in any case.
|
||||||
|
* Otherwise (probably) empty.
|
||||||
|
|
||||||
#### Example `--extended` output
|
#### Example `--extended` output
|
||||||
|
|
||||||
identifiers
|
identifiers
|
||||||
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 190 foobar
|
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 190 foobar
|
||||||
libraryFunction f int* libraryFunction(string s) stdin 99 Hello\nWorld
|
libraryFunction f int* libraryFunction(string s) stdin 99 Hello\nWorld int*
|
||||||
libraryVariable v int libraryVariable stdin 56 My variable
|
libraryVariable v int libraryVariable stdin 56 My variable int
|
||||||
libreTypes g stdin 298
|
libreTypes g stdin 298
|
||||||
|
|
||||||
#### Note
|
#### Note
|
||||||
|
@ -190,6 +196,9 @@ DCD's output will start with "identifiers" when completing at a left paren
|
||||||
character if the keywords *pragma*, *scope*, *__traits*, *extern*, or *version*
|
character if the keywords *pragma*, *scope*, *__traits*, *extern*, or *version*
|
||||||
were just before the paren.
|
were just before the paren.
|
||||||
|
|
||||||
|
Types in the calltips and typeOf column may not be complete, e.g. missing
|
||||||
|
template parameters or typeof expressions, etc.
|
||||||
|
|
||||||
### Parenthesis completion
|
### Parenthesis completion
|
||||||
|
|
||||||
When the first line of output is "calltips", the editor should display a function
|
When the first line of output is "calltips", the editor should display a function
|
||||||
|
|
|
@ -152,6 +152,14 @@ struct AutocompleteResponse
|
||||||
* Documentation associated with this symbol.
|
* Documentation associated with this symbol.
|
||||||
*/
|
*/
|
||||||
string documentation;
|
string documentation;
|
||||||
|
// when changing the behavior here, update README.md
|
||||||
|
/**
|
||||||
|
* For variables, fields, globals, constants: resolved type or empty if unresolved.
|
||||||
|
* For functions: resolved return type or empty if unresolved.
|
||||||
|
* For constructors: may be struct/class name or empty in any case.
|
||||||
|
* Otherwise (probably) empty.
|
||||||
|
*/
|
||||||
|
string typeOf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -445,6 +445,43 @@ struct DSymbol
|
||||||
/// Protection level for this symbol
|
/// Protection level for this symbol
|
||||||
IdType protection;
|
IdType protection;
|
||||||
|
|
||||||
|
string formatType(string suffix = "") const
|
||||||
|
{
|
||||||
|
if (kind == CompletionKind.functionName)
|
||||||
|
{
|
||||||
|
if (type) // try to give return type symbol
|
||||||
|
return type.formatType;
|
||||||
|
else // null if unresolved, user can manually pick .name or .callTip if needed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (name == POINTER_SYMBOL_NAME)
|
||||||
|
{
|
||||||
|
if (!type)
|
||||||
|
return suffix ~ "*";
|
||||||
|
else
|
||||||
|
return type.formatType(suffix ~ "*");
|
||||||
|
}
|
||||||
|
else if (name == ARRAY_SYMBOL_NAME)
|
||||||
|
{
|
||||||
|
if (!type)
|
||||||
|
return suffix ~ "[]";
|
||||||
|
else
|
||||||
|
return type.formatType(suffix ~ "[]");
|
||||||
|
}
|
||||||
|
else if (name == ASSOC_ARRAY_SYMBOL_NAME)
|
||||||
|
{
|
||||||
|
// TODO: include AA key type
|
||||||
|
if (!type)
|
||||||
|
return suffix ~ "[...]";
|
||||||
|
else
|
||||||
|
return type.formatType(suffix ~ "[...]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: include template parameters
|
||||||
|
return name ~ suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -217,8 +217,8 @@ unittest
|
||||||
};
|
};
|
||||||
ScopeSymbolPair pair = generateAutocompleteTrees(source, cache);
|
ScopeSymbolPair pair = generateAutocompleteTrees(source, cache);
|
||||||
DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife"));
|
DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife"));
|
||||||
writeln(meaningOfLife.type.name);
|
writeln(meaningOfLife.type.formatType);
|
||||||
assert(meaningOfLife.type.name == "int");
|
assert(meaningOfLife.type.formatType == "int*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -396,7 +396,8 @@ void printCompletionResponse(ref const AutocompleteResponse response, bool exten
|
||||||
completion.kind == char.init ? "" : "" ~ completion.kind,
|
completion.kind == char.init ? "" : "" ~ completion.kind,
|
||||||
completion.definition,
|
completion.definition,
|
||||||
completion.symbolFilePath.length ? completion.symbolFilePath ~ " " ~ completion.symbolLocation.to!string : "",
|
completion.symbolFilePath.length ? completion.symbolFilePath ~ " " ~ completion.symbolLocation.to!string : "",
|
||||||
completion.documentation
|
completion.documentation,
|
||||||
|
completion.typeOf
|
||||||
));
|
));
|
||||||
else
|
else
|
||||||
app.put(makeTabSeparated(completion.identifier, "" ~ completion.kind));
|
app.put(makeTabSeparated(completion.identifier, "" ~ completion.kind));
|
||||||
|
|
|
@ -701,5 +701,6 @@ do
|
||||||
auto completion = makeSymbolCompletionInfo(symbol, char.init);
|
auto completion = makeSymbolCompletionInfo(symbol, char.init);
|
||||||
completion.identifier = "this";
|
completion.identifier = "this";
|
||||||
completion.definition = generatedStructConstructorCalltip;
|
completion.definition = generatedStructConstructorCalltip;
|
||||||
|
completion.typeOf = symbol.name;
|
||||||
return completion;
|
return completion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -614,16 +614,26 @@ bool isUdaExpression(T)(ref T tokens)
|
||||||
|
|
||||||
AutocompleteResponse.Completion makeSymbolCompletionInfo(const DSymbol* symbol, char kind)
|
AutocompleteResponse.Completion makeSymbolCompletionInfo(const DSymbol* symbol, char kind)
|
||||||
{
|
{
|
||||||
string definition;
|
auto ret = AutocompleteResponse.Completion(symbol.name, kind, null,
|
||||||
if ((kind == CompletionKind.variableName || kind == CompletionKind.memberVariableName) && symbol.type)
|
|
||||||
definition = symbol.type.name ~ ' ' ~ symbol.name;
|
|
||||||
else if (kind == CompletionKind.enumMember)
|
|
||||||
definition = symbol.name; // TODO: add enum value to definition string
|
|
||||||
else
|
|
||||||
definition = symbol.callTip;
|
|
||||||
// TODO: definition strings could include more information, like on classes inheritance
|
|
||||||
return AutocompleteResponse.Completion(symbol.name, kind, definition,
|
|
||||||
symbol.symbolFile, symbol.location, symbol.doc);
|
symbol.symbolFile, symbol.location, symbol.doc);
|
||||||
|
|
||||||
|
if (symbol.type)
|
||||||
|
ret.typeOf = symbol.type.formatType;
|
||||||
|
|
||||||
|
if ((kind == CompletionKind.variableName || kind == CompletionKind.memberVariableName) && symbol.type)
|
||||||
|
{
|
||||||
|
if (symbol.type.kind == CompletionKind.functionName && !ret.typeOf.length)
|
||||||
|
ret.definition = symbol.type.name ~ ' ' ~ symbol.name;
|
||||||
|
else
|
||||||
|
ret.definition = ret.typeOf ~ ' ' ~ symbol.name;
|
||||||
|
}
|
||||||
|
else if (kind == CompletionKind.enumMember)
|
||||||
|
ret.definition = symbol.name; // TODO: add enum value to definition string
|
||||||
|
else
|
||||||
|
ret.definition = symbol.callTip;
|
||||||
|
|
||||||
|
// TODO: extend completion with more info such as class inheritance
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doUFCSSearch(string beforeToken, string lastToken)
|
bool doUFCSSearch(string beforeToken, string lastToken)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
identifiers
|
identifiers
|
||||||
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 190 foobar
|
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 223 foobar
|
||||||
libraryFunction f int* libraryFunction(string s) stdin 99 Hello\nWorld
|
libraryFunction f int* libraryFunction(string s) stdin 132 Hello\nWorld int*
|
||||||
libraryVariable v int libraryVariable stdin 56 My variable
|
libraryVariable v int libraryVariable stdin 56 My variable int
|
||||||
|
libraryVariable2 v int* libraryVariable2 stdin 88 My variable int*
|
||||||
|
|
|
@ -5,6 +5,8 @@ void main(string[] args)
|
||||||
|
|
||||||
/// My variable
|
/// My variable
|
||||||
int libraryVariable;
|
int libraryVariable;
|
||||||
|
/// ditto
|
||||||
|
int* libraryVariable2;
|
||||||
|
|
||||||
/// Hello
|
/// Hello
|
||||||
/// World
|
/// World
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
calltips
|
calltips
|
||||||
libraryFunction Tuple!long libraryFunction(string s, string s2) stdin 166 foobar
|
libraryFunction Tuple!long libraryFunction(string s, string s2) stdin 166 foobar
|
||||||
libraryFunction int* libraryFunction(string s) stdin 75 Hello\nWorld
|
libraryFunction int* libraryFunction(string s) stdin 75 Hello\nWorld int*
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
identifiers
|
identifiers
|
||||||
foo f void foo() stdin 26 my documentation
|
foo f void foo() stdin 26 my documentation void
|
||||||
foo f void foo(int i) stdin 49 my documentation
|
foo f void foo(int i) stdin 49 my documentation void
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
identifiers
|
||||||
|
bar v foo bar stdin 92
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// my documentation
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
T foo(T)() { return T.init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
S s;
|
||||||
|
auto bar = s.foo!int();
|
||||||
|
bar
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file.d -x -c115 > actual1.txt
|
||||||
|
diff actual1.txt expected1.txt --strip-trailing-cr
|
|
@ -2,5 +2,5 @@ set -e
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
../../bin/dcd-client $1 file.d --extended -I"$PWD"/newpackage -c$(wc -c < file.d) > actual1.txt
|
../../bin/dcd-client $1 file.d --extended -I"$PWD"/newpackage -c$(wc -c < file.d) > actual1.txt
|
||||||
echo -e "identifiers\nSomeStruct\ts\t\t$PWD/newpackage/newmodule.d 26\t" > expected1.txt
|
echo -e "identifiers\nSomeStruct\ts\t\t$PWD/newpackage/newmodule.d 26\t\t" > expected1.txt
|
||||||
diff actual1.txt expected1.txt --strip-trailing-cr
|
diff actual1.txt expected1.txt --strip-trailing-cr
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
identifiers
|
||||||
|
itemA v S itemA stdin 44 S
|
||||||
|
itemB v S* itemB stdin 55 S*
|
||||||
|
itemC v S[]* itemC stdin 68 S[]*
|
||||||
|
itemD v S[][]* itemD stdin 83 S[][]*
|
||||||
|
itemE v S[][]*[] itemE stdin 100 S[][]*[]
|
||||||
|
itemF v S[][]*[][] itemF stdin 119 S[][]*[][]
|
||||||
|
itemG v S[][...]*[][] itemG stdin 141 S[][...]*[][]
|
||||||
|
itemH v S[][]*[...][] itemH stdin 163 S[][]*[...][]
|
||||||
|
itemI v S[...][]*[...][] itemI stdin 188 S[...][]*[...][]
|
||||||
|
itemJ v S[...]*[]*[...][] itemJ stdin 214 S[...]*[]*[...][]
|
||||||
|
itemK v S[...]*[]**[...][] itemK stdin 241 S[...]*[]**[...][]
|
||||||
|
itemL v S[...]*[]*[...]*[] itemL stdin 268 S[...]*[]*[...]*[]
|
||||||
|
itemM v S[...]*[]*[...]*[]* itemM stdin 296 S[...]*[]*[...]*[]*
|
|
@ -0,0 +1,23 @@
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int member;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
S itemA;
|
||||||
|
S* itemB;
|
||||||
|
S[]* itemC;
|
||||||
|
S[][]* itemD;
|
||||||
|
S[][]*[] itemE;
|
||||||
|
S[][]*[][] itemF;
|
||||||
|
S[][int]*[][] itemG;
|
||||||
|
S[][]*[int][] itemH;
|
||||||
|
S[int][]*[int][] itemI;
|
||||||
|
S[int]*[]*[int][] itemJ;
|
||||||
|
S[int]*[]**[int][] itemK;
|
||||||
|
S[int]*[]*[int]*[] itemL;
|
||||||
|
S[int]*[]*[int]*[]* itemM;
|
||||||
|
|
||||||
|
item
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file.d -x -c309 > actual1.txt
|
||||||
|
diff actual1.txt expected1.txt --strip-trailing-cr
|
|
@ -4,5 +4,5 @@ set -u
|
||||||
echo "import: $PWD/testing"
|
echo "import: $PWD/testing"
|
||||||
|
|
||||||
../../bin/dcd-client $1 app.d --extended -I $PWD/ -c50 > actual.txt
|
../../bin/dcd-client $1 app.d --extended -I $PWD/ -c50 > actual.txt
|
||||||
echo -e "identifiers\nworld\tv\tWorld world\t$PWD/testing/a.d 77\t" > expected.txt
|
echo -e "identifiers\nworld\tv\tWorld world\t$PWD/testing/a.d 77\t\tWorld" > expected.txt
|
||||||
diff actual.txt expected.txt --strip-trailing-cr
|
diff actual.txt expected.txt --strip-trailing-cr
|
||||||
|
|
Loading…
Reference in New Issue