Skip to content

Commit f23ba38

Browse files
committed
lint: use globals.globalState, not context.globalState
1 parent 4489ec6 commit f23ba38

File tree

7 files changed

+102
-9
lines changed

7 files changed

+102
-9
lines changed

packages/core/src/auth/secondaryAuth.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ export class SecondaryAuth<T extends Connection = Connection> {
175175
}
176176

177177
public async saveConnection(conn: T) {
178+
// TODO: fix this
179+
// eslint-disable-next-line aws-toolkits/no-banned-usages
178180
await globals.context.globalState.update(this.key, conn.id)
179181
this.#savedConnection = conn
180182
this.#onDidChangeActiveConnection.fire(this.activeConnection)
@@ -206,6 +208,8 @@ export class SecondaryAuth<T extends Connection = Connection> {
206208

207209
/** Stop using the saved connection and fallback to using the active connection, if it is usable. */
208210
public async clearSavedConnection() {
211+
// TODO: fix this
212+
// eslint-disable-next-line aws-toolkits/no-banned-usages
209213
await globals.context.globalState.update(this.key, undefined)
210214
this.#savedConnection = undefined
211215
this.#onDidChangeActiveConnection.fire(this.activeConnection)
@@ -251,18 +255,21 @@ export class SecondaryAuth<T extends Connection = Connection> {
251255
})
252256

253257
private async loadSavedConnection() {
254-
const id = cast(globals.context.globalState.get(this.key), Optional(String))
258+
// TODO: fix this
259+
// eslint-disable-next-line aws-toolkits/no-banned-usages
260+
const globalState = globals.context.globalState
261+
const id = cast(globalState.get(this.key), Optional(String))
255262
if (id === undefined) {
256263
return
257264
}
258265

259266
const conn = await this.auth.getConnection({ id })
260267
if (conn === undefined) {
261268
getLogger().warn(`auth (${this.toolId}): removing saved connection "${this.key}" as it no longer exists`)
262-
await globals.context.globalState.update(this.key, undefined)
269+
await globalState.update(this.key, undefined)
263270
} else if (!this.isUsable(conn)) {
264271
getLogger().warn(`auth (${this.toolId}): saved connection "${this.key}" is not valid`)
265-
await globals.context.globalState.update(this.key, undefined)
272+
await globalState.update(this.key, undefined)
266273
} else {
267274
await this.auth.refreshConnectionState(conn)
268275
return conn

packages/core/src/dev/activation.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export type DevOptions = {
4848
}
4949

5050
let targetContext: vscode.ExtensionContext
51+
let globalState: vscode.Memento
5152
let targetAuth: Auth
5253

5354
/**
@@ -127,7 +128,7 @@ export class DevDocumentProvider implements vscode.TextDocumentContentProvider {
127128
} else if (uri.path.startsWith('/globalstate')) {
128129
// lol hax
129130
// as of November 2023, all of a memento's properties are stored as property `f` when minified
130-
return JSON.stringify((targetContext.globalState as any).f, undefined, 4)
131+
return JSON.stringify((globalState as any).f, undefined, 4)
131132
} else {
132133
return `unknown URI path: ${uri}`
133134
}
@@ -154,6 +155,8 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
154155
// Internal command to open dev menu for a specific context and options
155156
vscode.commands.registerCommand('_aws.dev.invokeMenu', (opts: DevOptions) => {
156157
targetContext = opts.context
158+
// eslint-disable-next-line aws-toolkits/no-banned-usages
159+
globalState = targetContext.globalState
157160
targetAuth = opts.auth
158161
void openMenu(
159162
entries(menuOptions)
@@ -298,7 +301,7 @@ class ObjectEditor {
298301
case 'globalsView':
299302
return showState('globalstate')
300303
case 'globals':
301-
return this.openState(targetContext.globalState, key)
304+
return this.openState(globalState, key)
302305
case 'secrets':
303306
return this.openState(targetContext.secrets, key)
304307
case 'auth':
@@ -381,7 +384,7 @@ async function openStorageFromInput() {
381384
return new SkipPrompter('')
382385
} else if (target === 'globals') {
383386
// List all globalState keys in the quickpick menu.
384-
const items = targetContext.globalState
387+
const items = globalState
385388
.keys()
386389
.map((key) => {
387390
return {

packages/core/src/shared/extensionGlobals.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ function proxyGlobals(globals_: ToolkitGlobals): ToolkitGlobals {
134134
let globals = proxyGlobals(resolveGlobalsObject())
135135

136136
export function checkDidReload(context: ExtensionContext): boolean {
137+
// TODO: fix this
138+
// eslint-disable-next-line aws-toolkits/no-banned-usages
137139
return !!context.globalState.get<string>('ACTIVATION_LAUNCH_PATH_KEY')
138140
}
139141

@@ -147,6 +149,7 @@ export function initialize(context: ExtensionContext, isWeb: boolean = false): T
147149
context,
148150
clock: copyClock(),
149151
didReload: checkDidReload(context),
152+
// eslint-disable-next-line aws-toolkits/no-banned-usages
150153
globalState: new GlobalState(context.globalState),
151154
manifestPaths: {} as ToolkitGlobals['manifestPaths'],
152155
visualizationResourcePaths: {} as ToolkitGlobals['visualizationResourcePaths'],

packages/core/src/test/fakeExtensionContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export class FakeExtensionContext implements vscode.ExtensionContext {
7474
*/
7575
private constructor(preload?: FakeExtensionState) {
7676
if (preload) {
77+
// eslint-disable-next-line aws-toolkits/no-banned-usages
7778
this.globalState = new FakeMemento(preload.globalState)
7879
this.workspaceState = new FakeMemento(preload.workspaceState)
7980
}

packages/core/src/test/globalSetup.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export async function mochaGlobalSetup(extensionId: string) {
5454
fakeContext.extensionPath = globals.context.extensionPath
5555
Object.assign(globals, {
5656
context: fakeContext,
57+
// eslint-disable-next-line aws-toolkits/no-banned-usages
5758
globalState: new GlobalState(fakeContext.globalState),
5859
})
5960
}

plugins/eslint-plugin-aws-toolkits/lib/rules/no-banned-usages.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { ESLintUtils } from '@typescript-eslint/utils'
6+
import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'
77
import { AST_NODE_TYPES } from '@typescript-eslint/types'
88
import { Rule } from 'eslint'
99
// import * as util from 'util'
1010

1111
export const errMsgs = {
12-
setContext: 'Use shared/vscode/setContext.ts, do not use executeCommand("setContext") directly',
12+
setContext: 'Use `shared/vscode/setContext.ts`, do not use `executeCommand("setContext")` directly',
13+
globalState: 'Use `globals.globalState`, do not use `ExtensionContext.globalState` directly or indirectly',
14+
}
15+
16+
/**
17+
* Each key is the member name, value is its expected container name.
18+
*/
19+
const memberContainers: Record<string, string> = {
20+
// Disallow accesses like `extContext.globalState` and `globals.context.globalState`.
21+
// Preferred usage is exactly: `globals.globalState`.
22+
globalState: 'globals',
1323
}
1424

1525
/**
@@ -31,6 +41,37 @@ export default ESLintUtils.RuleCreator.withoutDocs({
3141
defaultOptions: [],
3242
create(context) {
3343
return {
44+
MemberExpression(node: TSESTree.MemberExpression) {
45+
const o = node.object
46+
const p = node.property
47+
// Disallow accesses like: `banned1.member`.
48+
if (
49+
o.type === AST_NODE_TYPES.Identifier &&
50+
p.type === AST_NODE_TYPES.Identifier &&
51+
typeof memberContainers[p.name] === 'string' &&
52+
o.name !== memberContainers[p.name]
53+
) {
54+
return context.report({
55+
node,
56+
messageId: p.name as any,
57+
})
58+
}
59+
60+
// Disallow accesses like: `banned1.banned2.member`.
61+
if (
62+
o.type === AST_NODE_TYPES.MemberExpression &&
63+
o.object.type === AST_NODE_TYPES.Identifier &&
64+
p.type === AST_NODE_TYPES.Identifier &&
65+
typeof memberContainers[p.name] === 'string' &&
66+
o.property.type === AST_NODE_TYPES.Identifier &&
67+
o.property.name !== memberContainers[p.name]
68+
) {
69+
return context.report({
70+
node,
71+
messageId: p.name as any,
72+
})
73+
}
74+
},
3475
CallExpression(node) {
3576
if (
3677
node.callee.type !== AST_NODE_TYPES.MemberExpression ||

plugins/eslint-plugin-aws-toolkits/test/rules/no-banned-usages.test.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,20 @@ import { errMsgs } from '../../lib/rules/no-banned-usages'
88
import { getRuleTester } from '../testUtil'
99

1010
getRuleTester().run('no-banned-usages', rules['no-banned-usages'], {
11-
valid: ["vscode.commands.executeCommand('foo', 'aws.foo', true, 42)"],
11+
valid: [
12+
// setContext
13+
"vscode.commands.executeCommand('foo', 'aws.foo', true, 42)",
14+
// globalState
15+
'globals.globalState',
16+
'await globals.globalState.update("foo", 42)',
17+
'globals.globalState.get("foo")',
18+
'globalState.get("foo")',
19+
],
1220

1321
invalid: [
22+
//
23+
// setContext
24+
//
1425
{
1526
code: "async function test() { await vscode.commands.executeCommand('setContext', key, val) }",
1627
errors: [errMsgs.setContext],
@@ -35,5 +46,31 @@ getRuleTester().run('no-banned-usages', rules['no-banned-usages'], {
3546
code: "const x = vscode.commands.executeCommand('setContext', key, val).catch(e => { return e })",
3647
errors: [errMsgs.setContext],
3748
},
49+
50+
//
51+
// globalState
52+
//
53+
{
54+
code: 'const memento = globals.context.globalState',
55+
errors: [errMsgs.globalState],
56+
},
57+
{
58+
code: 'const val = globals.context.globalState.get("foo")',
59+
errors: [errMsgs.globalState],
60+
},
61+
{
62+
code: 'const val = extContext.globalState.get("foo")',
63+
errors: [errMsgs.globalState],
64+
},
65+
{
66+
code: 'return this.openState(targetContext.globalState, key)',
67+
errors: [errMsgs.globalState],
68+
},
69+
70+
// TODO: prevent assignment of GlobalState to Memento.
71+
// {
72+
// code: 'const state: vscode.Memento = globals.globalState',
73+
// errors: [errMsgs.globalState],
74+
// },
3875
],
3976
})

0 commit comments

Comments
 (0)