diff --git a/dsymbol/src/dsymbol/builtin/symbols.d b/dsymbol/src/dsymbol/builtin/symbols.d index 2675776..ac1dd7b 100644 --- a/dsymbol/src/dsymbol/builtin/symbols.d +++ b/dsymbol/src/dsymbol/builtin/symbols.d @@ -40,6 +40,11 @@ TTree!(DSymbol*, SymbolsAllocator, true, "a < b") classSymbols; */ TTree!(DSymbol*, SymbolsAllocator, true, "a < b") enumSymbols; +/** + * Pointer properties (when not implicitly dereferencing) + */ +TTree!(DSymbol*, SymbolsAllocator, true, "a < b") pointerSymbols; + /** * Variadic template parameters properties */ @@ -191,6 +196,12 @@ static this() aggregateSymbols.insert(stringof_); aggregateSymbols.insert(init); + pointerSymbols.insert(mangleof_); + pointerSymbols.insert(alignof_); + pointerSymbols.insert(sizeof_); + pointerSymbols.insert(stringof_); + pointerSymbols.insert(init); + classSymbols.insert(makeSymbol("classinfo", CompletionKind.variableName)); classSymbols.insert(tupleof); classSymbols.insert(makeSymbol("__vptr", CompletionKind.variableName)); @@ -283,6 +294,7 @@ static ~this() destroy(aggregateSymbols); destroy(classSymbols); destroy(enumSymbols); + destroy(pointerSymbols); foreach (sym; symbolsMadeHere[]) destroy(*sym); diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 14d3269..1ed1aad 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -1129,9 +1129,7 @@ private: foreach (suffix; type.typeSuffixes) { - if (suffix.star != tok!"") - continue; - else if (suffix.type) + if (suffix.type) lookup.breadcrumbs.insert(ASSOC_ARRAY_SYMBOL_NAME); else if (suffix.array) lookup.breadcrumbs.insert(ARRAY_SYMBOL_NAME); diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index a94795f..e6b1d4b 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -180,29 +180,30 @@ do while (!lookup.breadcrumbs.empty) { auto back = lookup.breadcrumbs.back; - immutable bool isArr = back == ARRAY_SYMBOL_NAME; - immutable bool isAssoc = back == ASSOC_ARRAY_SYMBOL_NAME; - immutable bool isFunction = back == FUNCTION_SYMBOL_NAME; - if (back == POINTER_SYMBOL_NAME) - { - lastSuffix.isPointer = true; - lookup.breadcrumbs.popBack(); - continue; - } - if (!isArr && !isAssoc && !isFunction) - break; - immutable qualifier = isAssoc ? SymbolQualifier.assocArray - : (isFunction ? SymbolQualifier.func : SymbolQualifier.array); + SymbolQualifier qualifier; + if (back == ARRAY_SYMBOL_NAME) qualifier = SymbolQualifier.array; + else if (back == ASSOC_ARRAY_SYMBOL_NAME) qualifier = SymbolQualifier.assocArray; + else if (back == FUNCTION_SYMBOL_NAME) qualifier = SymbolQualifier.func; + else if (back == POINTER_SYMBOL_NAME) qualifier = SymbolQualifier.pointer; + else break; + lastSuffix = GCAllocator.instance.make!DSymbol(back, CompletionKind.dummy, lastSuffix); lastSuffix.qualifier = qualifier; lastSuffix.ownType = true; - if (isFunction) + + final switch (qualifier) { + case SymbolQualifier.none: + case SymbolQualifier.selectiveImport: + assert(false, "this should never be generated"); + case SymbolQualifier.func: lookup.breadcrumbs.popBack(); lastSuffix.callTip = lookup.breadcrumbs.back(); + break; + case SymbolQualifier.array: lastSuffix.addChildren(arraySymbols[], false); break; + case SymbolQualifier.assocArray: lastSuffix.addChildren(assocArraySymbols[], false); break; + case SymbolQualifier.pointer: lastSuffix.addChildren(pointerSymbols[], false); break; } - else - lastSuffix.addChildren(isArr ? arraySymbols[] : assocArraySymbols[], false); if (suffix is null) suffix = lastSuffix; @@ -454,9 +455,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, if (currentSymbol is null) return; - // Index expressions can be an array index or an AA index + // Index expressions can be on a pointer, an array or an AA if (currentSymbol.qualifier == SymbolQualifier.array || currentSymbol.qualifier == SymbolQualifier.assocArray + || currentSymbol.qualifier == SymbolQualifier.pointer || currentSymbol.kind == CompletionKind.aliasName) { if (currentSymbol.type !is null) diff --git a/dsymbol/src/dsymbol/symbol.d b/dsymbol/src/dsymbol/symbol.d index d7203c4..3b6a9c6 100644 --- a/dsymbol/src/dsymbol/symbol.d +++ b/dsymbol/src/dsymbol/symbol.d @@ -131,6 +131,8 @@ enum SymbolQualifier : ubyte func, /// Selective import selectiveImport, + /// The symbol is a pointer + pointer, } /** @@ -228,6 +230,11 @@ struct DSymbol return; visited.insert(cast(size_t) &this); + // pointers are implicitly dereferenced on members (a single layer) + if (qualifier == SymbolQualifier.pointer + && this.type.qualifier != SymbolQualifier.pointer) + return type.getParts!OR(name, app, visited, onlyOne); + if (name is null) { foreach (part; parts[].filter!(a => a.name != IMPORT_SYMBOL_NAME)) @@ -427,10 +434,14 @@ struct DSymbol // dfmt off mixin(bitfields!(bool, "ownType", 1, bool, "skipOver", 1, - bool, "isPointer", 1, - ubyte, "", 5)); + ubyte, "", 6)); // dfmt on + deprecated bool isPointer() + { + return qualifier == SymbolQualifier.pointer; + } + /// Protection level for this symbol IdType protection; diff --git a/src/dcd/server/autocomplete/util.d b/src/dcd/server/autocomplete/util.d index 8bb84d3..ba22733 100644 --- a/src/dcd/server/autocomplete/util.d +++ b/src/dcd/server/autocomplete/util.d @@ -381,7 +381,8 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope, case tok!"[": if (symbols.length == 0) break loop; - if (symbols[0].qualifier == SymbolQualifier.array) + if (symbols[0].qualifier == SymbolQualifier.array + || symbols[0].qualifier == SymbolQualifier.pointer) { skip(tok!"[", tok!"]"); if (!isSliceExpression(tokens, i)) diff --git a/tests/tc_pointers/expected1.txt b/tests/tc_pointers/expected1.txt new file mode 100644 index 0000000..2147230 --- /dev/null +++ b/tests/tc_pointers/expected1.txt @@ -0,0 +1,30 @@ +identifiers +alignof k +init k +mangleof k +member v int member stdin 16 int +sizeof k +stringof k +tupleof k +identifiers +alignof k +init k +mangleof k +member v int member stdin 16 int +sizeof k +stringof k +tupleof k +identifiers +alignof k +init k +mangleof k +sizeof k +stringof k +identifiers +alignof k +init k +mangleof k +member v int member stdin 16 int +sizeof k +stringof k +tupleof k diff --git a/tests/tc_pointers/file.d b/tests/tc_pointers/file.d new file mode 100644 index 0000000..e2932de --- /dev/null +++ b/tests/tc_pointers/file.d @@ -0,0 +1,28 @@ +struct S +{ + int member; +} + +void test() +{ + S itemA; + itemA. +} + +void test2() +{ + S* itemPtr = &itemA; + itemPtr. +} + +void test3() +{ + S** itemPtrPtr = &itemA; + itemPtrPtr. +} + +void test3() +{ + S** itemPtrPtr = &itemA; + itemPtrPtr[10]. +} diff --git a/tests/tc_pointers/run.sh b/tests/tc_pointers/run.sh new file mode 100755 index 0000000..a40bb92 --- /dev/null +++ b/tests/tc_pointers/run.sh @@ -0,0 +1,8 @@ +set -e +set -u + +../../bin/dcd-client $1 file.d -x -c58 > actual1.txt +../../bin/dcd-client $1 file.d -x -c108 >> actual1.txt +../../bin/dcd-client $1 file.d -x -c165 >> actual1.txt +../../bin/dcd-client $1 file.d -x -c226 >> actual1.txt +diff actual1.txt expected1.txt --strip-trailing-cr