| 381 | // Pass in 'arrayResults' if a string[] result is possible and a delimited string result is undesirable. |
| 382 | // The string[] result will be copied into 'arrayResults'. |
| 383 | export function resolveVariables(input: string | undefined, additionalEnvironment?: Record<string, string | string[]>, arrayResults?: string[]): string { |
| 384 | if (!input) { |
| 385 | return ""; |
| 386 | } |
| 387 | |
| 388 | // jsonc parser may assign a non-string object to a string. |
| 389 | // TODO: https://github.com/microsoft/vscode-cpptools/issues/9414 |
| 390 | if (!isString(input)) { |
| 391 | const inputAny: any = input; |
| 392 | input = inputAny.toString(); |
| 393 | return input ?? ""; |
| 394 | } |
| 395 | |
| 396 | // Replace environment and configuration variables. |
| 397 | const regexp: () => RegExp = () => /\$\{((env|config|workspaceFolder)(\.|:))?(.*?)\}/g; |
| 398 | let ret: string = input; |
| 399 | const cycleCache = new Set<string>(); |
| 400 | while (!cycleCache.has(ret)) { |
| 401 | cycleCache.add(ret); |
| 402 | ret = ret.replace(regexp(), (match: string, ignored1: string | undefined, varType: string | undefined, ignored2: string | undefined, name: string) => { |
| 403 | let newValue: string | undefined; |
| 404 | switch (varType) { |
| 405 | // Historically, if the variable didn't have anything before the "." or ":" |
| 406 | // it was assumed to be an environment variable |
| 407 | case undefined: |
| 408 | case "env": { |
| 409 | if (additionalEnvironment) { |
| 410 | const v: string | string[] | undefined = additionalEnvironment[name]; |
| 411 | if (isString(v)) { |
| 412 | newValue = v; |
| 413 | } else if (input === match && isArrayOfString(v)) { |
| 414 | if (arrayResults !== undefined) { |
| 415 | arrayResults.push(...v); |
| 416 | newValue = ""; |
| 417 | break; |
| 418 | } else { |
| 419 | newValue = v.join(path.delimiter); |
| 420 | } |
| 421 | } |
| 422 | } |
| 423 | if (newValue === undefined) { |
| 424 | newValue = process.env[name]; |
| 425 | } |
| 426 | |
| 427 | // If the environment variable is not set, we return an empty string. Only do |
| 428 | // this for ${env:X} variables, not ${X} variables. |
| 429 | if (newValue === undefined && varType !== undefined) { |
| 430 | newValue = ""; |
| 431 | } |
| 432 | break; |
| 433 | } |
| 434 | case "config": { |
| 435 | const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); |
| 436 | if (config) { |
| 437 | newValue = config.get<string>(name); |
| 438 | } |
| 439 | break; |
| 440 | } |