|
1 | 1 | import * as widgetCfg from '@/providers/widgetRegistry/configuration'
|
2 |
| -import { makeArgument, makeMethod, makeModuleMethod } from '@/stores/suggestionDatabase/entry' |
| 2 | +import { GraphDb } from '@/stores/graph/graphDatabase' |
| 3 | +import { ComputedValueRegistry, type ExpressionInfo } from '@/stores/project/computedValueRegistry' |
| 4 | +import { SuggestionDb } from '@/stores/suggestionDatabase' |
| 5 | +import { |
| 6 | + makeArgument, |
| 7 | + makeConstructor, |
| 8 | + makeMethod, |
| 9 | + makeModule, |
| 10 | + makeModuleMethod, |
| 11 | + makeType, |
| 12 | + type SuggestionEntry, |
| 13 | +} from '@/stores/suggestionDatabase/entry' |
3 | 14 | import { Ast } from '@/util/ast'
|
4 | 15 | import {
|
5 | 16 | ArgumentApplication,
|
6 | 17 | ArgumentAst,
|
7 | 18 | ArgumentPlaceholder,
|
| 19 | + getMethodCallInfoRecursively, |
8 | 20 | interpretCall,
|
9 | 21 | } from '@/util/callTree'
|
10 | 22 | import { initializeFFI } from 'shared/ast/ffi'
|
| 23 | +import type { ExpressionUpdatePayload, MethodCall } from 'shared/languageServerTypes' |
11 | 24 | import { assert, expect, test } from 'vitest'
|
| 25 | +import type { AstId } from '../abstract' |
12 | 26 |
|
13 | 27 | await initializeFFI()
|
14 | 28 |
|
@@ -107,6 +121,150 @@ test.each`
|
107 | 121 | },
|
108 | 122 | )
|
109 | 123 |
|
| 124 | +interface TestCase { |
| 125 | + description: string |
| 126 | + code: string |
| 127 | + /** Index of sub-application for which the MethodCallInfo is available. */ |
| 128 | + subapplicationIndex: number |
| 129 | + /** Not applied arguments in available MethodCallInfo. */ |
| 130 | + notAppliedArguments: number[] |
| 131 | + /** Not applied arguments expected for the whole expression. */ |
| 132 | + expectedNotAppliedArguments: number[] |
| 133 | +} |
| 134 | + |
| 135 | +test.each([ |
| 136 | + { |
| 137 | + description: 'Base case', |
| 138 | + code: 'Aggregate_Column.Sum', |
| 139 | + subapplicationIndex: 0, |
| 140 | + notAppliedArguments: [0, 1], |
| 141 | + expectedNotAppliedArguments: [0, 1], |
| 142 | + }, |
| 143 | + { |
| 144 | + description: '1 arg, info on most inner subapplication.', |
| 145 | + code: 'Aggregate_Column.Sum x', |
| 146 | + subapplicationIndex: 1, |
| 147 | + notAppliedArguments: [0, 1], |
| 148 | + expectedNotAppliedArguments: [1], |
| 149 | + }, |
| 150 | + { |
| 151 | + description: '2 args, info on most inner subapplication.', |
| 152 | + code: 'Aggregate_Column.Sum x y', |
| 153 | + subapplicationIndex: 2, |
| 154 | + notAppliedArguments: [0, 1], |
| 155 | + expectedNotAppliedArguments: [], |
| 156 | + }, |
| 157 | + { |
| 158 | + description: '2 args, info on inner subapplication.', |
| 159 | + code: 'Aggregate_Column.Sum x y', |
| 160 | + subapplicationIndex: 1, |
| 161 | + notAppliedArguments: [1], |
| 162 | + expectedNotAppliedArguments: [], |
| 163 | + }, |
| 164 | + { |
| 165 | + description: '2 args, notAppliedArguments are incorrectly empty.', |
| 166 | + code: 'Aggregate_Column.Sum x y', |
| 167 | + subapplicationIndex: 2, |
| 168 | + notAppliedArguments: [], |
| 169 | + expectedNotAppliedArguments: [], |
| 170 | + }, |
| 171 | + { |
| 172 | + description: '1 arg, notAppliedArguments unsorted.', |
| 173 | + code: 'Aggregate_Column.Sum x', |
| 174 | + subapplicationIndex: 1, |
| 175 | + notAppliedArguments: [1, 0], |
| 176 | + expectedNotAppliedArguments: [1], |
| 177 | + }, |
| 178 | + { |
| 179 | + description: '1 named arg.', |
| 180 | + code: 'Aggregate_Column.Sum as=x', |
| 181 | + subapplicationIndex: 1, |
| 182 | + notAppliedArguments: [0, 1], |
| 183 | + expectedNotAppliedArguments: [0], |
| 184 | + }, |
| 185 | + { |
| 186 | + description: '2 named args.', |
| 187 | + code: 'Aggregate_Column.Sum as=x column=y', |
| 188 | + subapplicationIndex: 2, |
| 189 | + notAppliedArguments: [0, 1], |
| 190 | + expectedNotAppliedArguments: [], |
| 191 | + }, |
| 192 | + { |
| 193 | + description: '1 wrongly named arg.', |
| 194 | + code: 'Aggregate_Column.Sum bla=x', |
| 195 | + subapplicationIndex: 1, |
| 196 | + notAppliedArguments: [0, 1], |
| 197 | + expectedNotAppliedArguments: [0, 1], |
| 198 | + }, |
| 199 | + { |
| 200 | + description: '1 named & 1 unnamed args.', |
| 201 | + code: 'Aggregate_Column.Sum as=x y', |
| 202 | + subapplicationIndex: 2, |
| 203 | + notAppliedArguments: [0, 1], |
| 204 | + expectedNotAppliedArguments: [], |
| 205 | + }, |
| 206 | +] as TestCase[])( |
| 207 | + 'Getting MethodCallInfo for sub-applications: $description', |
| 208 | + ({ code, subapplicationIndex, notAppliedArguments, expectedNotAppliedArguments }: TestCase) => { |
| 209 | + const { db, expectedMethodCall, expectedSuggestion, setExpressionInfo } = |
| 210 | + prepareMocksForGetMethodCallTest() |
| 211 | + const ast = Ast.parse(code) |
| 212 | + const subApplication = nthSubapplication(ast, subapplicationIndex) |
| 213 | + assert(subApplication) |
| 214 | + db.updateExternalIds(ast) |
| 215 | + setExpressionInfo(subApplication.id, { |
| 216 | + typename: undefined, |
| 217 | + methodCall: { ...expectedMethodCall, notAppliedArguments }, |
| 218 | + payload: { type: 'Pending' } as ExpressionUpdatePayload, |
| 219 | + profilingInfo: [], |
| 220 | + }) |
| 221 | + |
| 222 | + const info = getMethodCallInfoRecursively(ast, db) |
| 223 | + expect(info?.methodCall).toEqual({ |
| 224 | + ...expectedMethodCall, |
| 225 | + notAppliedArguments: expectedNotAppliedArguments, |
| 226 | + }) |
| 227 | + expect(info?.suggestion).toEqual(expectedSuggestion) |
| 228 | + }, |
| 229 | +) |
| 230 | + |
| 231 | +function prepareMocksForGetMethodCallTest(): { |
| 232 | + db: GraphDb |
| 233 | + expectedMethodCall: MethodCall |
| 234 | + expectedSuggestion: SuggestionEntry |
| 235 | + setExpressionInfo: (id: AstId, info: ExpressionInfo) => void |
| 236 | +} { |
| 237 | + const suggestionDb = new SuggestionDb() |
| 238 | + suggestionDb.set(1, makeModule('Standard.Table.Aggregate_Column')) |
| 239 | + suggestionDb.set(2, makeType('Standard.Table.Aggregate_Column.Aggregate_Column')) |
| 240 | + const con = makeConstructor('Standard.Table.Aggregate_Column.Aggregate_Column.Sum') |
| 241 | + con.arguments = [makeArgument('column', 'Any'), makeArgument('as', 'Any')] |
| 242 | + suggestionDb.set(3, con) |
| 243 | + const expectedSuggestion = suggestionDb.get(3)! |
| 244 | + const registry = ComputedValueRegistry.Mock() |
| 245 | + const db = GraphDb.Mock(registry, suggestionDb) |
| 246 | + const expectedMethodCall = { |
| 247 | + methodPointer: { |
| 248 | + module: 'Standard.Table.Aggregate_Column', |
| 249 | + definedOnType: 'Standard.Table.Aggregate_Column.Aggregate_Column', |
| 250 | + name: 'Sum', |
| 251 | + }, |
| 252 | + notAppliedArguments: [0, 1], |
| 253 | + } |
| 254 | + const setExpressionInfo = (id: AstId, info: ExpressionInfo) => |
| 255 | + registry.db.set(db.idToExternal(id)!, info) |
| 256 | + return { db, expectedMethodCall, expectedSuggestion, setExpressionInfo } |
| 257 | +} |
| 258 | + |
| 259 | +/** Nth sub-application of the Ast.App call chain. 0th is a `root` itself. */ |
| 260 | +function nthSubapplication(root: Ast.Ast, n: number): Ast.Ast | undefined { |
| 261 | + let current: Ast.Ast | undefined = root |
| 262 | + for (let i = 0; i < n; i++) { |
| 263 | + current = current instanceof Ast.App ? current.function : undefined |
| 264 | + } |
| 265 | + return current |
| 266 | +} |
| 267 | + |
110 | 268 | function printArgPattern(application: ArgumentApplication | Ast.Ast) {
|
111 | 269 | const parts: string[] = []
|
112 | 270 | let current: ArgumentApplication['target'] = application
|
|
0 commit comments