Skip to content

Commit

Permalink
Resolve ptr, array & aa in types, add typeOf field
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
WebFreak001 committed Mar 16, 2023
1 parent 690d625 commit 22f65d5
Show file tree
Hide file tree
Showing 19 changed files with 151 additions and 21 deletions.
13 changes: 11 additions & 2 deletions README.md
Expand Up @@ -175,13 +175,19 @@ a tab separated format:
* 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.
* 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

identifiers
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 190 foobar
libraryFunction f int* libraryFunction(string s) stdin 99 Hello\nWorld
libraryVariable v int libraryVariable stdin 56 My variable
libraryFunction f int* libraryFunction(string s) stdin 99 Hello\nWorld int*
libraryVariable v int libraryVariable stdin 56 My variable int
libreTypes g stdin 298

#### Note
Expand All @@ -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*
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

When the first line of output is "calltips", the editor should display a function
Expand Down
8 changes: 8 additions & 0 deletions common/src/dcd/common/messages.d
Expand Up @@ -152,6 +152,14 @@ struct AutocompleteResponse
* Documentation associated with this symbol.
*/
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;
}

/**
Expand Down
37 changes: 37 additions & 0 deletions dsymbol/src/dsymbol/symbol.d
Expand Up @@ -445,6 +445,43 @@ struct DSymbol
/// Protection level for this symbol
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;
}
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions dsymbol/src/dsymbol/tests.d
Expand Up @@ -217,8 +217,8 @@ unittest
};
ScopeSymbolPair pair = generateAutocompleteTrees(source, cache);
DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife"));
writeln(meaningOfLife.type.name);
assert(meaningOfLife.type.name == "int");
writeln(meaningOfLife.type.formatType);
assert(meaningOfLife.type.formatType == "int*");
}


Expand Down
3 changes: 2 additions & 1 deletion src/dcd/client/client.d
Expand Up @@ -396,7 +396,8 @@ void printCompletionResponse(ref const AutocompleteResponse response, bool exten
completion.kind == char.init ? "" : "" ~ completion.kind,
completion.definition,
completion.symbolFilePath.length ? completion.symbolFilePath ~ " " ~ completion.symbolLocation.to!string : "",
completion.documentation
completion.documentation,
completion.typeOf
));
else
app.put(makeTabSeparated(completion.identifier, "" ~ completion.kind));
Expand Down
1 change: 1 addition & 0 deletions src/dcd/server/autocomplete/complete.d
Expand Up @@ -701,5 +701,6 @@ do
auto completion = makeSymbolCompletionInfo(symbol, char.init);
completion.identifier = "this";
completion.definition = generatedStructConstructorCalltip;
completion.typeOf = symbol.name;
return completion;
}
24 changes: 17 additions & 7 deletions src/dcd/server/autocomplete/util.d
Expand Up @@ -614,16 +614,26 @@ bool isUdaExpression(T)(ref T tokens)

AutocompleteResponse.Completion makeSymbolCompletionInfo(const DSymbol* symbol, char kind)
{
string definition;
auto ret = AutocompleteResponse.Completion(symbol.name, kind, null,
symbol.symbolFile, symbol.location, symbol.doc);

if (symbol.type)
ret.typeOf = symbol.type.formatType;

if ((kind == CompletionKind.variableName || kind == CompletionKind.memberVariableName) && symbol.type)
definition = symbol.type.name ~ ' ' ~ symbol.name;
{
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)
definition = symbol.name; // TODO: add enum value to definition string
ret.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);
ret.definition = symbol.callTip;

// TODO: extend completion with more info such as class inheritance
return ret;
}

bool doUFCSSearch(string beforeToken, string lastToken)
Expand Down
7 changes: 4 additions & 3 deletions tests/tc059/expected1.txt
@@ -1,4 +1,5 @@
identifiers
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 190 foobar
libraryFunction f int* libraryFunction(string s) stdin 99 Hello\nWorld
libraryVariable v int libraryVariable stdin 56 My variable
libraryFunction f Tuple!long libraryFunction(string s, string s2) stdin 223 foobar
libraryFunction f int* libraryFunction(string s) stdin 132 Hello\nWorld int*
libraryVariable v int libraryVariable stdin 56 My variable int
libraryVariable2 v int* libraryVariable2 stdin 88 My variable int*
2 changes: 2 additions & 0 deletions tests/tc059/file.d
Expand Up @@ -5,6 +5,8 @@ void main(string[] args)

/// My variable
int libraryVariable;
/// ditto
int* libraryVariable2;

/// Hello
/// World
Expand Down
4 changes: 2 additions & 2 deletions tests/tc061/expected1.txt
@@ -1,3 +1,3 @@
calltips
libraryFunction Tuple!long libraryFunction(string s, string s2) stdin 166 foobar
libraryFunction int* libraryFunction(string s) stdin 75 Hello\nWorld
libraryFunction Tuple!long libraryFunction(string s, string s2) stdin 166 foobar
libraryFunction int* libraryFunction(string s) stdin 75 Hello\nWorld int*
4 changes: 2 additions & 2 deletions tests/tc_extended_ditto/expected1.txt
@@ -1,3 +1,3 @@
identifiers
foo f void foo() stdin 26 my documentation
foo f void foo(int i) stdin 49 my documentation
foo f void foo() stdin 26 my documentation void
foo f void foo(int i) stdin 49 my documentation void
2 changes: 2 additions & 0 deletions tests/tc_extended_types/expected1.txt
@@ -0,0 +1,2 @@
identifiers
bar v foo bar stdin 92
12 changes: 12 additions & 0 deletions tests/tc_extended_types/file.d
@@ -0,0 +1,12 @@
/// my documentation
struct S
{
T foo(T)() { return T.init; }
}

void test()
{
S s;
auto bar = s.foo!int();
bar
}
5 changes: 5 additions & 0 deletions tests/tc_extended_types/run.sh
@@ -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 changes: 1 addition & 1 deletion tests/tc_import_symbol_list/run.sh
Expand Up @@ -2,5 +2,5 @@ set -e
set -u

../../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
14 changes: 14 additions & 0 deletions tests/tc_pointer_type_printing/expected1.txt
@@ -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[...]*[]*[...]*[]*
23 changes: 23 additions & 0 deletions tests/tc_pointer_type_printing/file.d
@@ -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
}
5 changes: 5 additions & 0 deletions tests/tc_pointer_type_printing/run.sh
@@ -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
2 changes: 1 addition & 1 deletion tests/tc_recursive_public_import/run.sh
Expand Up @@ -4,5 +4,5 @@ set -u
echo "import: $PWD/testing"

../../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

0 comments on commit 22f65d5

Please sign in to comment.