1 module workspaced.com.snippets.dependencies; 2 3 import workspaced.api; 4 import workspaced.com.dub; 5 import workspaced.com.snippets; 6 7 import std.algorithm; 8 9 /// 10 alias SnippetList = PlainSnippet[]; 11 12 /// A list of dependencies usable in an associative array 13 struct DependencySet 14 { 15 string[] sorted; 16 17 void set(string[] deps) 18 { 19 deps.sort!"a<b"; 20 sorted = deps; 21 } 22 23 bool hasAll(string[] deps) const 24 { 25 deps.sort!"a<b"; 26 int a, b; 27 while (a < sorted.length && b < deps.length) 28 { 29 const as = sorted[a]; 30 const bs = deps[b]; 31 const c = cmp(as, bs); 32 33 if (c == 0) 34 { 35 a++; 36 b++; 37 } 38 else if (c < 0) 39 return false; 40 else 41 b++; 42 } 43 return a == sorted.length; 44 } 45 46 bool opEquals(const ref DependencySet other) const 47 { 48 return sorted == other.sorted; 49 } 50 51 size_t toHash() const @safe nothrow 52 { 53 size_t ret; 54 foreach (v; sorted) 55 ret ^= typeid(v).getHash((() @trusted => &v)()); 56 return ret; 57 } 58 } 59 60 class DependencyBasedSnippetProvider : SnippetProvider 61 { 62 SnippetList[DependencySet] snippets; 63 64 void addSnippet(string[] requiredDependencies, PlainSnippet snippet) 65 { 66 DependencySet set; 67 set.set(requiredDependencies); 68 69 if (auto v = set in snippets) 70 *v ~= snippet; 71 else 72 snippets[set] = [snippet]; 73 } 74 75 Future!(Snippet[]) provideSnippets(scope const WorkspaceD.Instance instance, 76 scope const(char)[] file, scope const(char)[] code, int position, const SnippetInfo info) 77 { 78 if (!instance.has!DubComponent) 79 return typeof(return).fromResult(null); 80 else 81 { 82 string id = typeid(this).name; 83 auto dub = instance.get!DubComponent; 84 return typeof(return).async(delegate() { 85 string[] deps; 86 foreach (dep; dub.dependencies) 87 { 88 deps ~= dep.name; 89 deps ~= dep.dependencies.keys; 90 } 91 Snippet[] ret; 92 foreach (k, v; snippets) 93 { 94 if (k.hasAll(deps)) 95 { 96 foreach (snip; v) 97 if (snip.levels.canFind(info.level)) 98 ret ~= snip.buildSnippet(id); 99 } 100 } 101 return ret; 102 }); 103 } 104 } 105 106 Future!Snippet resolveSnippet(scope const WorkspaceD.Instance instance, 107 scope const(char)[] file, scope const(char)[] code, int position, 108 const SnippetInfo info, Snippet snippet) 109 { 110 snippet.resolved = true; 111 return typeof(return).fromResult(snippet); 112 } 113 } 114 115 unittest 116 { 117 DependencySet set; 118 set.set(["vibe-d", "mir", "serve-d"]); 119 assert(set.hasAll(["vibe-d", "serve-d", "mir"])); 120 assert(set.hasAll(["vibe-d", "serve-d", "serve-d", "serve-d", "mir", "mir"])); 121 assert(set.hasAll(["vibe-d", "serve-d", "mir", "workspace-d"])); 122 assert(set.hasAll(["diet-ng", "vibe-d", "serve-d", "mir", "workspace-d"])); 123 assert(!set.hasAll(["diet-ng", "serve-d", "mir", "workspace-d"])); 124 assert(!set.hasAll(["diet-ng", "serve-d", "vibe-d", "workspace-d"])); 125 assert(!set.hasAll(["diet-ng", "mir", "mir", "vibe-d", "workspace-d"])); 126 assert(!set.hasAll(["diet-ng", "mir", "vibe-d", "workspace-d"])); 127 128 set.set(["vibe-d:http"]); 129 assert(set.hasAll([ 130 "botan", "botan", "botan-math", "botan-math", "diet-ng", "diet-ng", 131 "eventcore", "eventcore", "libasync", "libasync", "memutils", 132 "memutils", "memutils", "mir-linux-kernel", "mir-linux-kernel", 133 "openssl", "openssl", "openssl", "stdx-allocator", "stdx-allocator", 134 "stdx-allocator", "taggedalgebraic", "taggedalgebraic", "vibe-core", 135 "vibe-core", "vibe-d", "vibe-d:core", "vibe-d:core", "vibe-d:core", 136 "vibe-d:core", "vibe-d:core", "vibe-d:core", "vibe-d:crypto", 137 "vibe-d:crypto", "vibe-d:crypto", "vibe-d:data", "vibe-d:data", 138 "vibe-d:data", "vibe-d:http", "vibe-d:http", "vibe-d:http", "vibe-d:http", 139 "vibe-d:http", "vibe-d:inet", "vibe-d:inet", "vibe-d:inet", "vibe-d:inet", 140 "vibe-d:mail", "vibe-d:mail", "vibe-d:mongodb", "vibe-d:mongodb", 141 "vibe-d:redis", "vibe-d:redis", "vibe-d:stream", "vibe-d:stream", 142 "vibe-d:stream", "vibe-d:stream", "vibe-d:textfilter", "vibe-d:textfilter", 143 "vibe-d:textfilter", "vibe-d:textfilter", "vibe-d:tls", "vibe-d:tls", 144 "vibe-d:tls", "vibe-d:tls", "vibe-d:utils", "vibe-d:utils", "vibe-d:utils", 145 "vibe-d:utils", "vibe-d:utils", "vibe-d:utils", "vibe-d:web", "vibe-d:web" 146 ])); 147 148 set.set(null); 149 assert(set.hasAll([])); 150 assert(set.hasAll(["foo"])); 151 }