Fixes #23, among other things

This commit is contained in:
Hackerpilot 2013-09-01 00:31:56 +00:00
parent 5ba4a47047
commit 616ea4feff
6 changed files with 90 additions and 58 deletions

View File

@ -90,6 +90,9 @@ public:
*/ */
ACSymbol[] parts; ACSymbol[] parts;
/**
* Listing of superclasses
*/
string[] superClasses; string[] superClasses;
/** /**
@ -159,6 +162,10 @@ public:
this.end = end; this.end = end;
} }
/**
* Gets all symbols in the scope that contains the cursor as well as its
* parent scopes.
*/
ACSymbol[] getSymbolsInCurrentScope(size_t cursorPosition) ACSymbol[] getSymbolsInCurrentScope(size_t cursorPosition)
{ {
Scope s = findCurrentScope(cursorPosition); Scope s = findCurrentScope(cursorPosition);
@ -168,6 +175,9 @@ public:
return s.getSymbols(); return s.getSymbols();
} }
/**
* Gets all symbols in this scope and its parent scopes.
*/
ACSymbol[] getSymbols() ACSymbol[] getSymbols()
{ {
ACSymbol[] rVal; ACSymbol[] rVal;
@ -229,20 +239,6 @@ public:
*/ */
void resolveSymbolTypes() void resolveSymbolTypes()
{ {
foreach (ref ACSymbol c; symbols.filter!(a => a.kind == CompletionKind.className
|| a.kind == CompletionKind.interfaceName))
{
foreach (string sc; c.superClasses)
{
ACSymbol[] s = findSymbolsInScope(sc);
if (s.length > 0)
{
foreach (part; s[0].parts)
c.parts ~= part;
}
}
}
// We only care about resolving types of variables, all other symbols // We only care about resolving types of variables, all other symbols
// don't have any indirection // don't have any indirection
foreach (ref s; symbols.filter!(a => (a.kind == CompletionKind.variableName foreach (ref s; symbols.filter!(a => (a.kind == CompletionKind.variableName
@ -321,10 +317,26 @@ public:
} }
} }
} }
foreach (c; children) foreach (c; children)
{ {
c.resolveSymbolTypes(); c.resolveSymbolTypes();
} }
foreach (ref ACSymbol c; symbols.filter!(a => a.kind == CompletionKind.className
|| a.kind == CompletionKind.interfaceName))
{
foreach (string sc; c.superClasses)
{
//writeln("Adding inherited fields from ", sc);
ACSymbol[] s = findSymbolsInScope(sc);
if (s.length > 0)
{
foreach (part; s[0].parts)
c.parts ~= part;
}
}
}
} }
/** /**

View File

@ -93,7 +93,7 @@ class AutocompleteVisitor : ASTVisitor
symbol.type = t; symbol.type = t;
symbol.kind = CompletionKind.variableName; symbol.kind = CompletionKind.variableName;
symbols ~= symbol; symbols ~= symbol;
writeln("For statement variable ", symbol.name, " of type ", symbol.type, " added."); //writeln("For statement variable ", symbol.name, " of type ", symbol.type, " added.");
} }
BlockStatement block = forStatement.statementNoCaseNoDefault.blockStatement; BlockStatement block = forStatement.statementNoCaseNoDefault.blockStatement;
auto s = new Scope(forStatement.startIndex, auto s = new Scope(forStatement.startIndex,
@ -105,14 +105,14 @@ class AutocompleteVisitor : ASTVisitor
foreach (symbol; symbols) foreach (symbol; symbols)
{ {
writeln("added ", symbol.name, " to scope"); //writeln("added ", symbol.name, " to scope");
symbol.location = scope_.start; symbol.location = scope_.start;
scope_.symbols ~= symbol; scope_.symbols ~= symbol;
} }
if (block.declarationsAndStatements !is null) if (block.declarationsAndStatements !is null)
{ {
writeln("visiting body"); //writeln("visiting body");
visit(block.declarationsAndStatements); visit(block.declarationsAndStatements);
} }
scope_ = p; scope_ = p;
@ -314,9 +314,23 @@ class AutocompleteVisitor : ASTVisitor
} }
} }
if (dec.returnType !is null && dec.parameters !is null) if (dec.parameters !is null)
{ {
symbol.calltip = format("%s %s%s", dec.returnType.toString(), string returnType;
if (dec.returnType !is null)
returnType = dec.returnType.toString();
else
{
if (dec.hasAuto)
{
returnType = "auto";
if (dec.hasRef)
returnType = "auto ref";
}
else if (dec.hasRef)
returnType = "ref";
}
symbol.calltip = format("%s %s%s", returnType,
dec.name.value, dec.parameters.toString()); dec.name.value, dec.parameters.toString());
} }
auto p = parentSymbol; auto p = parentSymbol;
@ -448,6 +462,23 @@ class AutocompleteVisitor : ASTVisitor
} }
} }
override void visit(BaseClassList classList)
{
if (parentSymbol is null)
return;
foreach (BaseClass bc; classList.items)
{
if (bc.identifierOrTemplateChain is null)
continue;
if (bc.identifierOrTemplateChain.identifiersOrTemplateInstances.length != 1)
continue;
IdentifierOrTemplateInstance i = bc.identifierOrTemplateChain.identifiersOrTemplateInstances[0];
if (i is null || i.identifier == TokenType.invalid)
continue;
parentSymbol.superClasses ~= i.identifier.value;
}
}
override void visit(BlockStatement blockStatement) override void visit(BlockStatement blockStatement)
{ {
auto s = scope_; auto s = scope_;

View File

@ -31,6 +31,7 @@ import std.uni;
import stdx.d.ast; import stdx.d.ast;
import stdx.d.lexer; import stdx.d.lexer;
import stdx.d.parser; import stdx.d.parser;
import std.string;
import messages; import messages;
import acvisitor; import acvisitor;
@ -38,7 +39,6 @@ import actypes;
import constants; import constants;
import modulecache; import modulecache;
AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths) AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
{ {
writeln("Got a completion request"); writeln("Got a completion request");
@ -180,7 +180,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
{ {
// writeln("Showing all symbols in current scope that start with ", partial); // writeln("Showing all symbols in current scope that start with ", partial);
foreach (s; visitor.scope_.getSymbolsInCurrentScope(cursorPosition) foreach (s; visitor.scope_.getSymbolsInCurrentScope(cursorPosition)
.filter!(a => a.name.startsWith(partial))) .filter!(a => a.name.toUpper().startsWith(partial.toUpper())))
{ {
response.completionKinds ~= s.kind; response.completionKinds ~= s.kind;
response.completions ~= s.name; response.completions ~= s.name;
@ -348,7 +348,8 @@ void setCompletions(T)(ref AutocompleteResponse response,
{ {
foreach (s; symbols[0].parts.filter!(a => a.name !is null foreach (s; symbols[0].parts.filter!(a => a.name !is null
&& a.name[0] != '*' && a.name[0] != '*'
&& (partial is null ? true : a.name.startsWith(partial)))) && (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper()))
&& !response.completions.canFind(a.name)))
{ {
//writeln("Adding ", s.name, " to the completion list"); //writeln("Adding ", s.name, " to the completion list");
response.completionKinds ~= s.kind; response.completionKinds ~= s.kind;
@ -515,16 +516,6 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response)
} }
} }
string createCamelCaseRegex(string input)
{
return to!string(input.map!(a => isLower(a) ? [a] : ".*"d ~ a).join());
}
unittest
{
assert("ClNa".createCamelCaseRegex() == "Cl.*Na.*");
}
/** /**
* Initializes builtin types and the various properties of builtin types * Initializes builtin types and the various properties of builtin types
*/ */

@ -1 +1 @@
Subproject commit 270cd6d9a1196ea802e79958605c9705c5ea22d4 Subproject commit ce53b1643b17b614adf222f932fb54831cb7c678

View File

@ -25,7 +25,7 @@ local function showCompletionList(r)
buffer.auto_c_choose_single = false; buffer.auto_c_choose_single = false;
buffer.auto_c_max_width = 0 buffer.auto_c_max_width = 0
local completions = {} local completions = {}
for symbol, kind in r:gmatch("([@%w_%p]+)\t(%a)\n") do for symbol, kind in r:gmatch("([^%s]+)\t(%a)\n") do
completion = symbol completion = symbol
if kind == "k" then if kind == "k" then
completion = completion .. "?5" completion = completion .. "?5"
@ -109,9 +109,6 @@ end)
function M.autocomplete(ch) function M.autocomplete(ch)
if buffer:get_lexer() ~= "dmd" then return end if buffer:get_lexer() ~= "dmd" then return end
if ch > 255 then return end
local character = string.char(ch)
if character == "." or character == "(" then
local fileName = os.tmpname() local fileName = os.tmpname()
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " > " .. fileName local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " > " .. fileName
local p = io.popen(command, "w") local p = io.popen(command, "w")
@ -120,7 +117,7 @@ function M.autocomplete(ch)
p:close() p:close()
local tmpFile = io.open(fileName, "r") local tmpFile = io.open(fileName, "r")
local r = tmpFile:read("*a") local r = tmpFile:read("*a")
--print(r) print(r)
if r ~= "\n" then if r ~= "\n" then
if r:match("^identifiers.*") then if r:match("^identifiers.*") then
showCompletionList(r) showCompletionList(r)
@ -130,7 +127,6 @@ function M.autocomplete(ch)
end end
os.remove(fileName) os.remove(fileName)
end end
end
M.ALIAS =[[ M.ALIAS =[[
/* XPM */ /* XPM */

View File

@ -11,12 +11,14 @@ if type(_G.keys) == 'table' then
end end
events.connect(events.CHAR_ADDED, function(ch) events.connect(events.CHAR_ADDED, function(ch)
if string.char(ch) == '(' or string.char(ch) == '.' then
_M.dcd.autocomplete(ch) _M.dcd.autocomplete(ch)
end
end) end)
local function autocomplete() local function autocomplete()
_M.dcd.registerImages() _M.dcd.registerImages()
_M.dcd.autocomplete(string.byte('.')) _M.dcd.autocomplete()
if not buffer:auto_c_active() then if not buffer:auto_c_active() then
_M.textadept.editing.autocomplete_word(keywords) _M.textadept.editing.autocomplete_word(keywords)
end end