Added --full output mode
This will send symbol location & documentation along with completions and calltips partly #20, fix #96, fix #269
This commit is contained in:
parent
38dfd9a32c
commit
172d45ce81
25
README.md
25
README.md
|
@ -135,6 +135,31 @@ tab character, followed by a completion kind
|
|||
calltip v
|
||||
getPartByName f
|
||||
|
||||
#### Extended output mode
|
||||
You can pass `--full` to dcd-client to get more information. Output will now be
|
||||
escaped (newlines get escaped to `\n`, tabs get escaped to `\t`, backslash gets escaped to `\\`).
|
||||
|
||||
Calltips are slightly different here because they first start with the function name instead of
|
||||
arguments and the second part will be blank. The actual calltip is now in the third column.
|
||||
|
||||
Columns may be empty, in which case there will be multiple tabs next to each other.
|
||||
|
||||
The following information will be available in every line for completion in this format then in
|
||||
a tab separated format:
|
||||
* identifier: raw name of a variable or function, etc
|
||||
* kind: empty for calltips, see above for rest
|
||||
* definition: function or variable definition string or close approximation for information display purpose
|
||||
* symbolFilePath: in which file this symbol is defined or `stdin`
|
||||
* symbolLocation: the byte offset at which the symbol is located in the file
|
||||
* documentation: escaped documentation string of this symbol
|
||||
|
||||
#### Example `--full` 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
|
||||
libreTypes g stdin 298
|
||||
|
||||
#### Note
|
||||
DCD's output will start with "identifiers" when completing at a left paren
|
||||
character if the keywords *pragma*, *scope*, *__traits*, *extern*, or *version*
|
||||
|
|
|
@ -51,6 +51,7 @@ int main(string[] args)
|
|||
bool listImports;
|
||||
bool getIdentifier;
|
||||
bool localUse;
|
||||
bool fullOutput;
|
||||
string search;
|
||||
version(Windows)
|
||||
{
|
||||
|
@ -73,7 +74,7 @@ int main(string[] args)
|
|||
"tcp", &useTCP, "socketFile", &socketFile,
|
||||
"getIdentifier", &getIdentifier,
|
||||
"localUsage", &localUse, // TODO:remove this line in Nov. 2017
|
||||
"localUse|u", &localUse);
|
||||
"localUse|u", &localUse, "full|2", &fullOutput);
|
||||
}
|
||||
catch (ConvException e)
|
||||
{
|
||||
|
@ -239,7 +240,7 @@ int main(string[] args)
|
|||
else if (localUse)
|
||||
printLocalUse(response);
|
||||
else
|
||||
printCompletionResponse(response);
|
||||
printCompletionResponse(response, fullOutput);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -288,6 +289,10 @@ Options:
|
|||
Searches for all the uses of the symbol at the cursor location
|
||||
in the given filename (or stdin).
|
||||
|
||||
--full | -2
|
||||
Includes more information with a slightly different format for
|
||||
calltips when autocompleting.
|
||||
|
||||
--query | -q | --status
|
||||
Query the server statis. Returns 0 if the server is running. Returns
|
||||
1 if the server could not be contacted.
|
||||
|
@ -343,16 +348,14 @@ Socket createSocket(string socketFile, ushort port)
|
|||
void printDocResponse(ref const AutocompleteResponse response)
|
||||
{
|
||||
import std.algorithm : each;
|
||||
response.docComments.each!(writeln);
|
||||
response.completions.each!(a => a.documentation.escapeTabValue(true).writeln);
|
||||
}
|
||||
|
||||
void printIdentifierResponse(ref const AutocompleteResponse response)
|
||||
{
|
||||
if (response.completions.length == 0)
|
||||
return;
|
||||
write(response.completions[0]);
|
||||
write("\t");
|
||||
writeln(response.symbolIdentifier);
|
||||
writeln(makeTabSeparated(response.completions[0].identifier, response.symbolIdentifier.to!string));
|
||||
}
|
||||
|
||||
void printLocationResponse(ref const AutocompleteResponse response)
|
||||
|
@ -360,26 +363,35 @@ void printLocationResponse(ref const AutocompleteResponse response)
|
|||
if (response.symbolFilePath is null)
|
||||
writeln("Not found");
|
||||
else
|
||||
writefln("%s\t%d", response.symbolFilePath, response.symbolLocation);
|
||||
writeln(makeTabSeparated(response.symbolFilePath, response.symbolLocation.to!string));
|
||||
}
|
||||
|
||||
void printCompletionResponse(ref const AutocompleteResponse response)
|
||||
void printCompletionResponse(ref const AutocompleteResponse response, bool full)
|
||||
{
|
||||
if (response.completions.length > 0)
|
||||
{
|
||||
writeln(response.completionType);
|
||||
auto app = appender!(string[])();
|
||||
if (response.completionType == CompletionType.identifiers)
|
||||
if (response.completionType == CompletionType.identifiers || full)
|
||||
{
|
||||
for (size_t i = 0; i < response.completions.length; i++)
|
||||
app.put(format("%s\t%s", response.completions[i], response.completionKinds[i]));
|
||||
foreach (ref completion; response.completions)
|
||||
{
|
||||
if (full)
|
||||
app.put(makeTabSeparated(
|
||||
completion.identifier,
|
||||
completion.kind == char.init ? "" : "" ~ completion.kind,
|
||||
completion.definition,
|
||||
completion.symbolFilePath.length ? completion.symbolFilePath ~ " " ~ completion.symbolLocation.to!string : "",
|
||||
completion.documentation
|
||||
));
|
||||
else
|
||||
app.put(makeTabSeparated(completion.identifier, "" ~ completion.kind));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (completion; response.completions)
|
||||
{
|
||||
app.put(completion);
|
||||
}
|
||||
app.put(completion.definition);
|
||||
}
|
||||
// Deduplicate overloaded methods
|
||||
foreach (line; app.data.sort().uniq)
|
||||
|
@ -389,20 +401,17 @@ void printCompletionResponse(ref const AutocompleteResponse response)
|
|||
|
||||
void printSearchResponse(const AutocompleteResponse response)
|
||||
{
|
||||
foreach(i; 0 .. response.completions.length)
|
||||
{
|
||||
writefln("%s\t%s\t%s", response.completions[i], response.completionKinds[i],
|
||||
response.locations[i]);
|
||||
}
|
||||
foreach(ref completion; response.completions)
|
||||
writeln(makeTabSeparated(completion.identifier, "" ~ completion.kind, completion.symbolLocation.to!string));
|
||||
}
|
||||
|
||||
void printLocalUse(const AutocompleteResponse response)
|
||||
{
|
||||
if (response.symbolFilePath.length)
|
||||
{
|
||||
writeln(response.symbolFilePath, '\t', response.symbolLocation);
|
||||
foreach(loc; response.locations)
|
||||
writeln(loc);
|
||||
writeln(makeTabSeparated(response.symbolFilePath, response.symbolLocation.to!string));
|
||||
foreach(loc; response.completions)
|
||||
writeln(loc.symbolLocation);
|
||||
}
|
||||
else write("00000");
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -120,6 +120,44 @@ struct AutocompleteRequest
|
|||
*/
|
||||
struct AutocompleteResponse
|
||||
{
|
||||
static struct Completion
|
||||
{
|
||||
/**
|
||||
* The name of the symbol for a completion, for calltips just the function name.
|
||||
*/
|
||||
string identifier;
|
||||
/**
|
||||
* The kind of the item. Will be char.init for calltips.
|
||||
*/
|
||||
char kind;
|
||||
/**
|
||||
* Definition for a symbol for a completion including attributes or the arguments for calltips.
|
||||
*/
|
||||
string definition;
|
||||
/**
|
||||
* The path to the file that contains the symbol.
|
||||
*/
|
||||
string symbolFilePath;
|
||||
/**
|
||||
* The byte offset at which the symbol is located or symbol location for symbol searches.
|
||||
*/
|
||||
size_t symbolLocation;
|
||||
/**
|
||||
* Documentation associated with this symbol.
|
||||
*/
|
||||
string documentation;
|
||||
|
||||
deprecated("Use identifier (or definition for calltips) instead") string compatibilityContent() const
|
||||
{
|
||||
if (kind == char.init)
|
||||
return definition;
|
||||
else
|
||||
return identifier;
|
||||
}
|
||||
|
||||
alias compatibilityContent this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The autocompletion type. (Parameters or identifier)
|
||||
*/
|
||||
|
@ -135,26 +173,10 @@ struct AutocompleteResponse
|
|||
*/
|
||||
size_t symbolLocation;
|
||||
|
||||
/**
|
||||
* The documentation comment
|
||||
*/
|
||||
string[] docComments;
|
||||
|
||||
/**
|
||||
* The completions
|
||||
*/
|
||||
string[] completions;
|
||||
|
||||
/**
|
||||
* The kinds of the items in the completions array. Will be empty if the
|
||||
* completion type is a function argument list.
|
||||
*/
|
||||
char[] completionKinds;
|
||||
|
||||
/**
|
||||
* Symbol locations for symbol searches.
|
||||
*/
|
||||
size_t[] locations;
|
||||
Completion[] completions;
|
||||
|
||||
/**
|
||||
* Import paths that are registered by the server.
|
||||
|
@ -166,6 +188,30 @@ struct AutocompleteResponse
|
|||
*/
|
||||
ulong symbolIdentifier;
|
||||
|
||||
deprecated("use completions[].documentation + escapeTabValue instead") string[] docComments() @property
|
||||
{
|
||||
string[] ret;
|
||||
foreach (ref completion; completions)
|
||||
ret ~= completion.documentation.escapeTabValue(true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
deprecated("use completions[].kind instead") char[] completionKinds() @property
|
||||
{
|
||||
char[] ret;
|
||||
foreach (ref completion; completions)
|
||||
ret ~= completion.kind;
|
||||
return ret;
|
||||
}
|
||||
|
||||
deprecated("use completions[].symbolLocation instead") size_t[] locations() @property
|
||||
{
|
||||
size_t[] ret;
|
||||
foreach (ref completion; completions)
|
||||
ret ~= completion.symbolLocation;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty acknowledgement response
|
||||
*/
|
||||
|
@ -246,3 +292,51 @@ bool serverIsRunning(bool useTCP, string socketFile, ushort port)
|
|||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Escapes \n, \t and \ in the string. If single is true \t won't be escaped.
|
||||
string escapeTabValue(string s, bool single = false)
|
||||
{
|
||||
import std.array : Appender;
|
||||
|
||||
Appender!(char[]) app;
|
||||
void putChar(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\\':
|
||||
app.put('\\');
|
||||
app.put('\\');
|
||||
break;
|
||||
case '\n':
|
||||
app.put('\\');
|
||||
app.put('n');
|
||||
break;
|
||||
case '\t':
|
||||
if (single)
|
||||
goto default;
|
||||
else
|
||||
{
|
||||
app.put('\\');
|
||||
app.put('t');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
app.put(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (char c; s)
|
||||
putChar(c);
|
||||
|
||||
return app.data.idup;
|
||||
}
|
||||
|
||||
/// Joins string arguments with tabs and escapes them
|
||||
string makeTabSeparated(string[] args...)
|
||||
{
|
||||
import std.algorithm : map;
|
||||
import std.array : join;
|
||||
|
||||
return args.map!(a => a.escapeTabValue).join("\t");
|
||||
}
|
||||
|
|
|
@ -127,10 +127,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
|||
{
|
||||
mixin(STRING_LITERAL_CASES);
|
||||
foreach (symbol; arraySymbols)
|
||||
{
|
||||
response.completionKinds ~= symbol.kind;
|
||||
response.completions ~= symbol.name.dup;
|
||||
}
|
||||
response.completions ~= makeSymbolCompletionInfo(symbol, symbol.kind);
|
||||
response.completionType = CompletionType.identifiers;
|
||||
break;
|
||||
mixin(TYPE_IDENT_CASES);
|
||||
|
@ -169,7 +166,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
|||
const(Token)[] tokenArray, size_t cursorPosition, ref ModuleCache moduleCache)
|
||||
{
|
||||
AutocompleteResponse response;
|
||||
immutable(string)[] completions;
|
||||
immutable(ConstantCompletion)[] completions;
|
||||
switch (beforeTokens[$ - 2].type)
|
||||
{
|
||||
case tok!"__traits":
|
||||
|
@ -190,8 +187,12 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
|||
response.completionType = CompletionType.identifiers;
|
||||
foreach (completion; completions)
|
||||
{
|
||||
response.completions ~= completion;
|
||||
response.completionKinds ~= CompletionKind.keyword;
|
||||
response.completions ~= AutocompleteResponse.Completion(
|
||||
completion.identifier,
|
||||
CompletionKind.keyword,
|
||||
null, null, 0, // definition, symbol path+location
|
||||
completion.ddoc
|
||||
);
|
||||
}
|
||||
break;
|
||||
case tok!"characterLiteral":
|
||||
|
@ -310,8 +311,7 @@ body
|
|||
&& !sy.skipOver && sy.name != CONSTRUCTOR_SYMBOL_NAME
|
||||
&& isPublicCompletionKind(sy.kind))
|
||||
{
|
||||
response.completionKinds ~= sy.kind;
|
||||
response.completions ~= sy.name;
|
||||
response.completions ~= makeSymbolCompletionInfo(sy, sy.kind);
|
||||
h.insert(sy.name);
|
||||
}
|
||||
}
|
||||
|
@ -361,10 +361,7 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response,
|
|||
auto n = importPath.baseName(".d").baseName(".di");
|
||||
if (isFile(importPath) && (importPath.endsWith(".d") || importPath.endsWith(".di"))
|
||||
&& (partial is null || n.startsWith(partial)))
|
||||
{
|
||||
response.completions ~= n;
|
||||
response.completionKinds ~= CompletionKind.moduleName;
|
||||
}
|
||||
response.completions ~= AutocompleteResponse.Completion(n, CompletionKind.moduleName, null, importPath, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -383,18 +380,18 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response,
|
|||
auto n = name.baseName(".d").baseName(".di");
|
||||
if (isFile(name) && (name.endsWith(".d") || name.endsWith(".di"))
|
||||
&& (partial is null || n.startsWith(partial)))
|
||||
{
|
||||
response.completions ~= n;
|
||||
response.completionKinds ~= CompletionKind.moduleName;
|
||||
}
|
||||
response.completions ~= AutocompleteResponse.Completion(n, CompletionKind.moduleName, null, name, 0);
|
||||
else if (isDir(name))
|
||||
{
|
||||
if (n[0] != '.' && (partial is null || n.startsWith(partial)))
|
||||
{
|
||||
response.completions ~= n;
|
||||
response.completionKinds ~=
|
||||
exists(buildPath(name, "package.d")) || exists(buildPath(name, "package.di"))
|
||||
? CompletionKind.moduleName : CompletionKind.packageName;
|
||||
string packageDPath = buildPath(name, "package.d");
|
||||
string packageDIPath = buildPath(name, "package.di");
|
||||
bool packageD = exists(packageDPath);
|
||||
bool packageDI = exists(packageDIPath);
|
||||
auto kind = packageD || packageDI ? CompletionKind.moduleName : CompletionKind.packageName;
|
||||
string file = packageD ? packageDPath : packageDI ? packageDIPath : name;
|
||||
response.completions ~= AutocompleteResponse.Completion(n, kind, null, file, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,11 +421,10 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
{
|
||||
if (sym.name !is null && sym.name.length > 0 && isPublicCompletionKind(sym.kind)
|
||||
&& (p is null ? true : toUpper(sym.name.data).startsWith(toUpper(p)))
|
||||
&& !r.completions.canFind(sym.name)
|
||||
&& !r.completions.canFind!(a => a.identifier == sym.name)
|
||||
&& sym.name[0] != '*')
|
||||
{
|
||||
r.completionKinds ~= sym.kind;
|
||||
r.completions ~= sym.name.dup;
|
||||
r.completions ~= makeSymbolCompletionInfo(sym, sym.kind);
|
||||
}
|
||||
if (sym.kind == CompletionKind.importSymbol && !sym.skipOver && sym.type !is null)
|
||||
addSymToResponse(sym.type, r, p, circularGuard ~ (cast(size_t) s));
|
||||
|
@ -443,8 +439,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
foreach (s; currentSymbols.filter!(a => isPublicCompletionKind(a.kind)
|
||||
&& toUpper(a.name.data).startsWith(toUpper(partial))))
|
||||
{
|
||||
response.completionKinds ~= s.kind;
|
||||
response.completions ~= s.name.dup;
|
||||
response.completions ~= makeSymbolCompletionInfo(s, s.kind);
|
||||
}
|
||||
response.completionType = CompletionType.identifiers;
|
||||
return;
|
||||
|
@ -539,12 +534,16 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
foreach (symbol; symbols)
|
||||
{
|
||||
if (symbol.kind != CompletionKind.aliasName && symbol.callTip !is null)
|
||||
response.completions ~= symbol.callTip;
|
||||
{
|
||||
auto completion = makeSymbolCompletionInfo(symbol, char.init);
|
||||
// TODO: put return type
|
||||
response.completions ~= completion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string generateStructConstructorCalltip(const DSymbol* symbol)
|
||||
AutocompleteResponse.Completion generateStructConstructorCalltip(const DSymbol* symbol)
|
||||
in
|
||||
{
|
||||
assert(symbol.kind == CompletionKind.structName);
|
||||
|
@ -570,5 +569,8 @@ body
|
|||
generatedStructConstructorCalltip ~= ", ";
|
||||
}
|
||||
generatedStructConstructorCalltip ~= ")";
|
||||
return generatedStructConstructorCalltip;
|
||||
auto completion = makeSymbolCompletionInfo(symbol, char.init);
|
||||
completion.identifier = "this";
|
||||
completion.definition = generatedStructConstructorCalltip;
|
||||
return completion;
|
||||
}
|
||||
|
|
|
@ -53,8 +53,6 @@ public AutocompleteResponse getDoc(const AutocompleteRequest request,
|
|||
warning("Could not find symbol");
|
||||
else
|
||||
{
|
||||
Appender!(char[]) app;
|
||||
|
||||
bool isDitto(string s)
|
||||
{
|
||||
import std.uni : icmp;
|
||||
|
@ -64,35 +62,11 @@ public AutocompleteResponse getDoc(const AutocompleteRequest request,
|
|||
return s.icmp("ditto") == 0;
|
||||
}
|
||||
|
||||
void putDDocChar(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\\':
|
||||
app.put('\\');
|
||||
app.put('\\');
|
||||
break;
|
||||
case '\n':
|
||||
app.put('\\');
|
||||
app.put('n');
|
||||
break;
|
||||
default:
|
||||
app.put(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void putDDocString(string s)
|
||||
{
|
||||
foreach (char c; s)
|
||||
putDDocChar(c);
|
||||
}
|
||||
|
||||
foreach(ref symbol; stuff.symbols.filter!(a => !a.doc.empty && !isDitto(a.doc)))
|
||||
{
|
||||
app.clear;
|
||||
putDDocString(symbol.doc);
|
||||
response.docComments ~= app.data.idup;
|
||||
AutocompleteResponse.Completion c;
|
||||
c.documentation = symbol.doc;
|
||||
response.completions ~= c;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
|
|
|
@ -104,7 +104,9 @@ public AutocompleteResponse findLocalUse(AutocompleteRequest request,
|
|||
candidate.symbols[0].location == sourceSymbol.location &&
|
||||
candidate.symbols[0].symbolFile == sourceSymbol.symbolFile)
|
||||
{
|
||||
response.locations ~= t.index;
|
||||
AutocompleteResponse.Completion c;
|
||||
c.symbolLocation = t.index;
|
||||
response.completions ~= c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,11 +116,7 @@ public AutocompleteResponse symbolSearch(const AutocompleteRequest request,
|
|||
|
||||
AutocompleteResponse response;
|
||||
foreach (result; results.tree[])
|
||||
{
|
||||
response.locations ~= result.symbol.location;
|
||||
response.completionKinds ~= result.symbol.kind;
|
||||
response.completions ~= result.symbol.symbolFile;
|
||||
}
|
||||
response.completions ~= makeSymbolCompletionInfo(result.symbol, result.symbol.kind);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
|
|
@ -738,3 +738,16 @@ unittest
|
|||
i = skipParenReverseBefore(t, i, tok!")", tok!"(");
|
||||
assert(i == 1);
|
||||
}
|
||||
|
||||
AutocompleteResponse.Completion makeSymbolCompletionInfo(const DSymbol* symbol, char kind)
|
||||
{
|
||||
string definition;
|
||||
if ((kind == 'v' || kind == 'm') && symbol.type)
|
||||
definition = symbol.type.name ~ ' ' ~ symbol.name;
|
||||
else if (kind == 'e')
|
||||
definition = symbol.name;
|
||||
else
|
||||
definition = symbol.callTip;
|
||||
return AutocompleteResponse.Completion(symbol.name, kind, definition,
|
||||
symbol.symbolFile, symbol.location, symbol.doc);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
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
|
|
@ -0,0 +1,20 @@
|
|||
void main(string[] args)
|
||||
{
|
||||
libr
|
||||
}
|
||||
|
||||
/// My variable
|
||||
int libraryVariable;
|
||||
|
||||
/// Hello
|
||||
/// World
|
||||
int* libraryFunction(string s) pure {
|
||||
return &libraryVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* foobar
|
||||
*/
|
||||
Tuple!long libraryFunction(string s, string s2) pure @nogc {
|
||||
return tuple(cast(long) (s.length * s2.length));
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
set -e
|
||||
set -u
|
||||
|
||||
../../bin/dcd-client $1 file.d --full -c32 > actual1.txt
|
||||
diff actual1.txt expected1.txt
|
|
@ -0,0 +1 @@
|
|||
extern()
|
|
@ -0,0 +1,16 @@
|
|||
set -e
|
||||
set -u
|
||||
|
||||
../../bin/dcd-client $1 --full file.d -c7 > actual1.txt
|
||||
|
||||
minimumsize=100 # identifiers + the symbols without documentation + some margin
|
||||
actualsize=$(wc -c < "actual1.txt")
|
||||
|
||||
# we don't want to unittest the documentation, so we just check if there is something that makes it longer than it would be
|
||||
|
||||
if [ $actualsize -ge $minimumsize ]; then
|
||||
exit 0
|
||||
else
|
||||
cat actual1.txt
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,3 @@
|
|||
calltips
|
||||
libraryFunction Tuple!long libraryFunction(string s, string s2) stdin 166 foobar
|
||||
libraryFunction int* libraryFunction(string s) stdin 75 Hello\nWorld
|
|
@ -0,0 +1,17 @@
|
|||
void main(string[] args)
|
||||
{
|
||||
libraryFunction();
|
||||
}
|
||||
|
||||
/// Hello
|
||||
/// World
|
||||
int* libraryFunction(string s) pure {
|
||||
return &libraryVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* foobar
|
||||
*/
|
||||
Tuple!long libraryFunction(string s, string s2) pure @nogc {
|
||||
return tuple(cast(long) (s.length * s2.length));
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
set -e
|
||||
set -u
|
||||
|
||||
../../bin/dcd-client $1 file.d --full -c44 > actual1.txt
|
||||
diff actual1.txt expected1.txt
|
Loading…
Reference in New Issue