2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { Iterable } from '../../../../base/common/iterator.js';
7
>
import { isLinux, isMacintosh, isWindows } from '../../../../base/common/platform.js';
8
>
import { ConfiguredInput } from './configurationResolver.js';
9
>
10
>
/** A replacement found in the object, as ${name} or ${name:arg} */
11
>
export type Replacement = {
12
>
/** ${name:arg} */
13
>
id: string;
14
>
/** The `name:arg` in ${name:arg} */
15
>
inner: string;
16
>
/** The `name` in ${name:arg} */
17
>
name: string;
18
>
/** The `arg` in ${name:arg} */
19
>
arg?: string;
20
>
};
21
>
22
>
interface IConfigurationResolverExpression<T> {
23
>
/**
24
>
* Gets the replacements which have not yet been
25
>
* resolved.
26
>
*/
27
>
unresolved(): Iterable<Replacement>;
28
>
29
>
/**
30
>
* Gets the replacements which have been resolved.
31
>
*/
32
>
resolved(): Iterable<[Replacement, IResolvedValue]>;
33
>
34
>
/**
35
>
* Resolves a replacement into the string value.
36
>
* If the value is undefined, the original variable text will be preserved.
37
>
*/
38
>
resolve(replacement: Replacement, data: string | IResolvedValue): void;
39
>
40
>
/**
41
>
* Returns the complete object. Any unresolved replacements are left intact.
42
>
*/
43
>
toObject(): T;
44
>
}
45
>
46
>
type PropertyLocation = {
47
>
object: any;
48
>
propertyName: string | number;
49
>
replaceKeyName?: boolean;
50
>
};
51
>
52
>
export interface IResolvedValue {
53
>
value: string | undefined;
54
>
55
>
/** Present when the variable is resolved from an input field. */
56
>
input?: ConfiguredInput;
57
>
}
58
>
59
>
interface IReplacementLocation {
60
>
replacement: Replacement;
61
>
locations: PropertyLocation[];
62
>
resolved?: IResolvedValue;
63
>
}
64
>
65
>
export class ConfigurationResolverExpression<T> implements IConfigurationResolverExpression<T> {
66
>
public static readonly VARIABLE_LHS = '${';
67
>
68
>
private readonly locations = new Map<string, IReplacementLocation>();
69
>
private root: T;
70
>
private stringRoot: boolean;
71
>
/**
72
>
* Callbacks when a new replacement is made, so that nested resolutions from
73
>
* `expr.unresolved()` can be fulfilled in the same iteration.
74
>
*/
75
>
private newReplacementNotifiers = new Set<(r: Replacement) => void>();
76
>
77
>
private constructor(object: T) {
78
// If the input is a string, wrap it in an object so we can use the same logic
79
if (typeof object === 'string') {