Skip to content

Commit

Permalink
feat: show type arguments in labels
Browse files Browse the repository at this point in the history
closes #19
  • Loading branch information
mxsdev committed Nov 20, 2022
1 parent b9b49ff commit 1c062c7
Show file tree
Hide file tree
Showing 24 changed files with 79,663 additions and 1,321 deletions.
7 changes: 5 additions & 2 deletions packages/api/src/localizedTree.ts
Expand Up @@ -20,8 +20,6 @@ import { getEmptyTypeId, pseudoBigIntToString } from "./util"
import { SymbolFlags } from "./typescript"
import { wrapSafe, isEmpty, isNonEmpty } from "./objectUtil"

// TODO: optional param booleans can sometimes become undefined|true|false (should just be boolean)

export function _localizeTypeInfo(
info: TypeInfo,
resolved: ResolvedArrayTypeInfo,
Expand Down Expand Up @@ -51,13 +49,18 @@ export function _localizeTypeInfo(
(originalInfo.kind === "array" && originalInfo.readonly) ||
(info.kind === "tuple" && info.readonly)

const typeArguments = info.typeArguments ?? opts.typeArguments

const res: LocalizedTypeInfo = {
kindText: getKind(info),
kind: info.kind,
...(info.kind === "primitive" && { primitiveKind: info.primitive }),
alias: getAlias(info),
symbol,
purpose,
...(isNonEmpty(typeArguments) && {
typeArguments: typeArguments.map((info) => ({ info })),
}),
...(isOptional && { optional: true }),
...(isRest && { rest: true }),
...(dimension && { dimension }),
Expand Down
7 changes: 5 additions & 2 deletions packages/api/src/resolveTree.ts
Expand Up @@ -41,13 +41,16 @@ export class TypeInfoResolver {
}

async localizeChildren(
parent: LocalizedTypeInfo
parent: LocalizedTypeInfo,
typeArguments = false
): Promise<LocalizedTypeInfo[]> {
const parentOrigin = this.localizedInfoOrigin.get(parent)
assert(parentOrigin)

const targets = !typeArguments ? parent.children : parent.typeArguments

return await Promise.all(
parent.children?.map(async ({ info, localizedInfo, opts }) => {
targets?.map(async ({ info, localizedInfo, opts }) => {
assert(
info || localizedInfo,
"Either info or localized info must be provided"
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/types.ts
Expand Up @@ -285,6 +285,7 @@ export type LocalizedTypeInfo = {
* Symbol info associated with this type, if any
*/
symbol?: LocalizedSymbolInfo
typeArguments?: TypeInfoChildren
/**
* Resolved type name
*/
Expand Down
12 changes: 12 additions & 0 deletions packages/typescript-explorer-vscode/package.json
Expand Up @@ -95,6 +95,18 @@
"title": "Max Recursion Depth",
"type": "integer",
"default": 6
},
"typescriptExplorer.typeTree.meta.typeArguments.enable": {
"type": "boolean",
"default": true
},
"typescriptExplorer.typeTree.meta.typeArguments.maxLength": {
"type": "integer",
"default": 10
},
"typescriptExplorer.typeTree.meta.typeArguments.includeInFunctions": {
"type": "boolean",
"default": false
}
}
},
Expand Down
9 changes: 9 additions & 0 deletions packages/typescript-explorer-vscode/src/config.ts
Expand Up @@ -17,10 +17,16 @@ const typeTreeConfigBoolean = {
const basicConfigBoolean = {
dialogueErrors: "typescriptExplorer.errorMessages.showDialogue",
logErrors: "typescriptExplorer.errorMessages.log",
descriptionTypeArgumentsEnabled:
"typescriptExplorer.typeTree.meta.typeArguments.enable",
metaTypeArgumentsInFunction:
"typescriptExplorer.typeTree.meta.typeArguments.includeInFunctions",
} as const

const basicConfigNumeric = {
maxRecursionDepth: "typescriptExplorer.typeTree.maxRecursionDepth",
descriptionTypeArgumentsMaxLength:
"typescriptExplorer.typeTree.meta.typeArguments.maxLength",
}

const exportBooleanConfig = (id: string, defaultValue?: boolean) =>
Expand Down Expand Up @@ -73,6 +79,9 @@ export const {
logErrors,
dialogueErrors,
maxRecursionDepth,
descriptionTypeArgumentsMaxLength,
descriptionTypeArgumentsEnabled,
metaTypeArgumentsInFunction,
} = {
...mapObject(typeTreeConfigBoolean, ({ value: [id] }) =>
exportBooleanConfig(id)
Expand Down
16 changes: 11 additions & 5 deletions packages/typescript-explorer-vscode/src/test/suite/basic.test.ts
Expand Up @@ -5,8 +5,8 @@ import {
openTestCase,
rangeFromPosition,
typeTreeProvider,
updateConfig,
waitForTypeTreeChildChange,
withConfig,
} from "../testLibrary"

const arrayPos = rangeFromPosition(0, 15)
Expand Down Expand Up @@ -36,10 +36,16 @@ suite("Basic Tests", () => {
const { children } = await waitForTypeTreeChildChange()
assert(children[0].iconPath)

updateConfig("typescriptExplorer.typeTree.view.icons.enable", false)

const { children: updatedChildren } = await waitForTypeTreeChildChange()
assert(!updatedChildren[0].iconPath)
await withConfig(
{
"typescriptExplorer.typeTree.view.icons.enable": false,
},
async () => {
const { children: updatedChildren } =
await waitForTypeTreeChildChange()
assert(!updatedChildren[0].iconPath)
}
)
})

test("lock works", async () => {
Expand Down
@@ -1,9 +1,4 @@
import {
clearConfigUpdates,
clearListeners,
focusTreeView,
initListeners,
} from "../testLibrary"
import { clearListeners, focusTreeView, initListeners } from "../testLibrary"

import * as extension from "../../extension"

Expand Down Expand Up @@ -32,5 +27,4 @@ beforeEach(async () => {

afterEach(async () => {
clearListeners()
await clearConfigUpdates()
})
@@ -0,0 +1,54 @@
import * as assert from "assert"
import * as vscode from "vscode"
import * as extension from "../../extension"
import {
openTestCase,
rangeFromPosition,
typeTreeProvider,
waitForTypeTreeChildChange,
withConfig,
} from "../testLibrary"

suite("Promise args", () => {
test("has simple type args", async () => {
const { fileName } = await openTestCase("promiseFunction.ts")
extension.stateManager.selectTypeAtPosition(fileName, [
rangeFromPosition(0, 24),
])

await waitForTypeTreeChildChange()
const { children } = await waitForTypeTreeChildChange()

const item = await extension.stateManager.typeTreeProvider?.getTreeItem(
children[0]
)

assert(item?.description === "Promise<string> (object)")
})

test(
"works for functions",
withConfig(
{
"typescriptExplorer.typeTree.meta.typeArguments.includeInFunctions":
true,
},
async () => {
const { fileName } = await openTestCase("mapArray.ts")
extension.stateManager.selectTypeAtPosition(fileName, [
rangeFromPosition(0, 20),
])

const { children } = await waitForTypeTreeChildChange()
await waitForTypeTreeChildChange()

const item =
await extension.stateManager.typeTreeProvider?.getTreeItem(
children[0]
)

assert(item?.label === "map<string>")
}
)
)
})
33 changes: 15 additions & 18 deletions packages/typescript-explorer-vscode/src/test/testLibrary.ts
Expand Up @@ -4,6 +4,7 @@ import * as vscode from "vscode"
import * as extension from "../extension"
import { TypeTreeItem } from "../view/typeTreeView"
import * as assert from "assert"
import { pairs } from "../functionalUtil"

function testCasePath(fileName: string) {
return path.join(__dirname, "../../../../tests/cases", fileName)
Expand Down Expand Up @@ -120,30 +121,26 @@ function clearArray<T>(arr: T[]) {
arr.splice(0, arr.length)
}

const configUpdateStack: [section: string, global: boolean][] = []

export function updateConfig<T>(section: string, value: T, global = true) {
configUpdateStack.push([section, global])
function updateConfig<T>(section: string, value: T, global = true) {
return vscode.workspace.getConfiguration().update(section, value, global)
}

export async function clearConfigUpdates() {
await Promise.all(
configUpdateStack
.reverse()
.map(([section, global]) =>
vscode.workspace
.getConfiguration()
.update(section, undefined, global)
)
)

clearArray(configUpdateStack)
}

export function rangeFromPosition(line: number, character: number) {
return new vscode.Range(
new vscode.Position(line, character),
new vscode.Position(line, character)
)
}

export function withConfig(
config: Record<string, any>,
callback: () => Promise<void>
) {
return async function () {
for (const { key, value } of pairs(config)) {
updateConfig(key, value)
await callback()
updateConfig(key, undefined)
}
}
}

0 comments on commit 1c062c7

Please sign in to comment.