From fd17b5975e1a58ea5dbadbb7d781de492f74cd06 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 15 Sep 2021 02:58:06 -0400 Subject: [PATCH] [vscode] support managing string keys and manage typescript.tsdk (#112185) (#112210) Co-authored-by: spalger Co-authored-by: Spencer Co-authored-by: spalger --- .../src/vscode_config/managed_config_keys.ts | 7 +- .../update_vscode_config.test.ts | 69 ++++++++++++++----- .../src/vscode_config/update_vscode_config.ts | 66 ++++++++++++------ 3 files changed, 102 insertions(+), 40 deletions(-) diff --git a/packages/kbn-dev-utils/src/vscode_config/managed_config_keys.ts b/packages/kbn-dev-utils/src/vscode_config/managed_config_keys.ts index 288bfad02d7f..8b941e9e4f71 100644 --- a/packages/kbn-dev-utils/src/vscode_config/managed_config_keys.ts +++ b/packages/kbn-dev-utils/src/vscode_config/managed_config_keys.ts @@ -8,7 +8,7 @@ export interface ManagedConfigKey { key: string; - value: Record; + value: string | Record; } /** @@ -37,4 +37,9 @@ export const MANAGED_CONFIG_KEYS: ManagedConfigKey[] = [ ['**/packages/kbn-pm/dist/index.js']: true, }, }, + { + key: 'typescript.tsdk', + // we use a relative path here so that it works with remote vscode connections + value: './node_modules/typescript/lib', + }, ]; diff --git a/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.test.ts b/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.test.ts index dd57449c21da..3573acd59559 100644 --- a/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.test.ts +++ b/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.test.ts @@ -22,6 +22,10 @@ const TEST_KEYS: ManagedConfigKey[] = [ world: [1, 2, 3], }, }, + { + key: 'stringKey', + value: 'foo', + }, ]; const run = (json?: string) => updateVscodeConfig(TEST_KEYS, '', json); @@ -35,7 +39,9 @@ it('updates the passed JSON with the managed settings', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -50,7 +56,9 @@ it('initialized empty or undefined json values', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -63,14 +71,16 @@ it('initialized empty or undefined json values', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); }); -it('replaces conflicting managed keys which do not have object values', () => { - expect(run(`{ "key": false }`)).toMatchInlineSnapshot(` +it('replaces conflicting managed keys which do not have matching value types', () => { + expect(run(`{ "key": false, "stringKey": { "a": "B" } }`)).toMatchInlineSnapshot(` // @managed { "key": { @@ -78,7 +88,9 @@ it('replaces conflicting managed keys which do not have object values', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -122,7 +134,9 @@ it('persists comments in the original file', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -148,7 +162,9 @@ it('overrides old values for managed keys', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -176,7 +192,9 @@ it('does not modify properties with leading `// self managed` comment', () => { // self managed "key": { "world": [5] - } + }, + // self managed + "stringKey": "--" } `); @@ -186,7 +204,9 @@ it('does not modify properties with leading `// self managed` comment', () => { // self managed "key": { "world": [5] - } + }, + // self managed + "stringKey": "--" } `); @@ -210,7 +230,9 @@ it('does not modify child properties with leading `// self managed` comment', () "world": [5], // @managed "hello": true - } + }, + // @managed + "stringKey": "foo" } `); @@ -236,7 +258,9 @@ it('does not modify unknown child properties', () => { "world": [5], // @managed "hello": true - } + }, + // @managed + "stringKey": "foo" } `); @@ -262,7 +286,9 @@ it('removes managed properties which are no longer managed', () => { "world": [5], // @managed "hello": true - } + }, + // @managed + "stringKey": "foo" } `); @@ -286,7 +312,9 @@ it('wipes out child keys which conflict with newly managed child keys', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -308,7 +336,9 @@ it('correctly formats info text when specified', () => { "hello": true, // @managed "world": [1, 2, 3] - } + }, + // @managed + "stringKey": "foo" } `); @@ -321,7 +351,10 @@ it('allows "// self managed" comments conflicting with "// @managed" comments to // @managed // self managed "hello": ["world"] - } + }, + // @managed + // self managed + "stringKey": 12345 } `); @@ -333,7 +366,9 @@ it('allows "// self managed" comments conflicting with "// @managed" comments to "hello": ["world"], // @managed "world": [1, 2, 3] - } + }, + // self managed + "stringKey": 12345 } `); diff --git a/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.ts b/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.ts index ac1b5515252d..42a642ef1b6c 100644 --- a/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.ts +++ b/packages/kbn-dev-utils/src/vscode_config/update_vscode_config.ts @@ -25,11 +25,20 @@ const isManaged = (node?: t.Node) => (c) => c.type === 'CommentLine' && c.value.trim().toLocaleLowerCase() === '@managed' ); -const isSelfManaged = (node?: t.Node) => - !!node?.leadingComments?.some( +const isSelfManaged = (node?: t.Node) => { + const result = !!node?.leadingComments?.some( (c) => c.type === 'CommentLine' && c.value.trim().toLocaleLowerCase() === 'self managed' ); + // if we find a node which is both managed and self managed remove the managed comment + if (result && node && isManaged(node)) { + node.leadingComments = + node.leadingComments?.filter((c) => c.value.trim() !== '@managed') ?? null; + } + + return result; +}; + const remove = (arr: T[], value: T) => { const index = arr.indexOf(value); if (index > -1) { @@ -37,16 +46,16 @@ const remove = (arr: T[], value: T) => { } }; -const createManagedChildProp = (key: string, value: any) => { +const createManagedProp = (key: string, value: any) => { const childProp = t.objectProperty(t.stringLiteral(key), parseExpression(JSON.stringify(value))); t.addComment(childProp, 'leading', ' @managed', true); return childProp; }; -const createManagedProp = (key: string, value: Record) => { +const createObjectPropOfManagedValues = (key: string, value: Record) => { return t.objectProperty( t.stringLiteral(key), - t.objectExpression(Object.entries(value).map(([k, v]) => createManagedChildProp(k, v))) + t.objectExpression(Object.entries(value).map(([k, v]) => createManagedProp(k, v))) ); }; @@ -57,8 +66,16 @@ const createManagedProp = (key: string, value: Record) => { * @param key the key name to add * @param value managed value which should be set at `key` */ -const addManagedProp = (ast: t.ObjectExpression, key: string, value: Record) => { - ast.properties.push(createManagedProp(key, value)); +const addManagedProp = ( + ast: t.ObjectExpression, + key: string, + value: string | Record +) => { + ast.properties.push( + typeof value === 'string' + ? createManagedProp(key, value) + : createObjectPropOfManagedValues(key, value) + ); }; /** @@ -72,7 +89,7 @@ const addManagedProp = (ast: t.ObjectExpression, key: string, value: Record + value: string | Record ) => { remove(ast.properties, existing); addManagedProp(ast, existing.key.value, value); @@ -98,15 +115,11 @@ const mergeManagedProperties = ( if (!existing) { // add the new managed prop - properties.push(createManagedChildProp(key, value)); + properties.push(createManagedProp(key, value)); continue; } if (isSelfManaged(existing)) { - // strip "// @managed" comment if conflicting with "// self managed" - existing.leadingComments = (existing.leadingComments ?? []).filter( - (c) => c.value.trim() !== '@managed' - ); continue; } @@ -119,7 +132,7 @@ const mergeManagedProperties = ( // take over the unmanaged child prop by deleting the previous prop and replacing it // with a brand new one remove(properties, existing); - properties.push(createManagedChildProp(key, value)); + properties.push(createManagedProp(key, value)); } // iterate through the props to find "// @managed" props which are no longer in @@ -170,20 +183,29 @@ export function updateVscodeConfig(keys: ManagedConfigKey[], infoText: string, j continue; } - if (existingProp && existingProp.value.type === 'ObjectExpression') { - // setting exists and is an object so merge properties of `value` with it - mergeManagedProperties(existingProp.value.properties, value); + if (typeof value === 'object') { + if (existingProp && existingProp.value.type === 'ObjectExpression') { + // setting exists and is an object so merge properties of `value` with it + mergeManagedProperties(existingProp.value.properties, value); + continue; + } + + if (existingProp) { + // setting exists but its value is not an object expression so replace it + replaceManagedProp(ast, existingProp, value); + continue; + } + + // setting isn't in config file so create it + addManagedProp(ast, key, value); continue; } if (existingProp) { - // setting exists but its value is not an object expression so replace it replaceManagedProp(ast, existingProp, value); - continue; + } else { + addManagedProp(ast, key, value); } - - // setting isn't in config file so create it - addManagedProp(ast, key, value); } ast.leadingComments = [