1 /** 2 * This file is part of DCD, a development tool for the D programming language. 3 * Copyright (C) 2014 Brian Schott 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 module dcd.server.autocomplete.symbols; 20 21 import std.experimental.logger; 22 import std.typecons; 23 24 import dcd.server.autocomplete.util; 25 26 import dparse.lexer; 27 import dparse.rollback_allocator; 28 29 import dsymbol.conversion; 30 import dsymbol.modulecache; 31 import dsymbol.string_interning; 32 import dsymbol.symbol; 33 34 import dcd.common.messages; 35 36 import containers.hashset; 37 38 /** 39 * Finds the declaration of the symbol at the cursor position. 40 * Params: 41 * request = the autocompletion request 42 * Returns: 43 * the autocompletion response 44 */ 45 public AutocompleteResponse findDeclaration(const AutocompleteRequest request, 46 ref ModuleCache moduleCache) 47 { 48 AutocompleteResponse response; 49 RollbackAllocator rba; 50 auto allocator = scoped!(ASTAllocator)(); 51 auto cache = StringCache(StringCache.defaultBucketCount); 52 SymbolStuff stuff = getSymbolsForCompletion(request, 53 CompletionType.location, allocator, &rba, cache, moduleCache); 54 scope(exit) stuff.destroy(); 55 if (stuff.symbols.length > 0) 56 { 57 response.symbolLocation = stuff.symbols[0].location; 58 response.symbolFilePath = stuff.symbols[0].symbolFile.idup; 59 } 60 else 61 warning("Could not find symbol declaration"); 62 return response; 63 } 64 65 /** 66 * 67 */ 68 public AutocompleteResponse symbolSearch(const AutocompleteRequest request, 69 ref ModuleCache moduleCache) 70 { 71 import containers.ttree : TTree; 72 73 LexerConfig config; 74 config.fileName = ""; 75 auto cache = StringCache(StringCache.defaultBucketCount); 76 const(Token)[] tokenArray = getTokensForParser(cast(ubyte[]) request.sourceCode, 77 config, &cache); 78 auto allocator = scoped!(ASTAllocator)(); 79 RollbackAllocator rba; 80 ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator, 81 &rba, request.cursorPosition, moduleCache); 82 scope(exit) pair.destroy(); 83 84 static struct SearchResults 85 { 86 void put(const(DSymbol)* symbol) 87 { 88 tree.insert(SearchResult(symbol)); 89 } 90 91 static struct SearchResult 92 { 93 const(DSymbol)* symbol; 94 95 int opCmp(ref const SearchResult other) const pure nothrow @nogc @safe 96 { 97 if (other.symbol.symbolFile < symbol.symbolFile) 98 return -1; 99 if (other.symbol.symbolFile > symbol.symbolFile) 100 return 1; 101 if (other.symbol.location < symbol.location) 102 return -1; 103 return other.symbol.location > symbol.location; 104 } 105 } 106 107 TTree!(SearchResult) tree; 108 } 109 110 SearchResults results; 111 HashSet!size_t visited; 112 foreach (symbol; pair.scope_.symbols) 113 symbol.getParts!SearchResults(internString(request.searchName), results, visited); 114 foreach (s; moduleCache.getAllSymbols()) 115 s.symbol.getParts!SearchResults(internString(request.searchName), results, visited); 116 117 AutocompleteResponse response; 118 foreach (result; results.tree[]) 119 response.completions ~= makeSymbolCompletionInfo(result.symbol, result.symbol.kind); 120 121 return response; 122 }