Skip to content

Commit

Permalink
fix(api): resolve symbol declarations
Browse files Browse the repository at this point in the history
closes #16
  • Loading branch information
mxsdev committed Nov 9, 2022
1 parent 701714b commit 4d6640f
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 17 deletions.
31 changes: 25 additions & 6 deletions packages/api/src/localizedTree.ts
@@ -1,5 +1,6 @@
import { getKindText, getPrimitiveKindText } from "./localization"
import {
DeclarationInfo,
IndexInfo,
LocalizableKind,
LocalizeData,
Expand Down Expand Up @@ -62,7 +63,7 @@ export function _localizeTypeInfo(
...(dimension && { dimension }),
...(name !== undefined && { name }),
...(readonly && { readonly: true }),
locations,
...(isNonEmpty(locations) && { locations }),
}

res.children = getChildren(info, opts)
Expand Down Expand Up @@ -553,11 +554,27 @@ function getKind(info: ResolvedTypeInfo): string {
}

function getTypeLocations(info: TypeInfo): SourceFileLocation[] | undefined {
const baseLocations = wrapSafe(getLocations)(
info.aliasSymbolMeta ?? info.symbolMeta
)
const baseDeclarations: DeclarationInfo[] = []

if (info.symbolMeta?.resolvedDeclarations) {
baseDeclarations.push(...info.symbolMeta.resolvedDeclarations)
}

const aliasSymbolDeclarations =
info.aliasSymbolMeta?.resolvedDeclarations ??
info.aliasSymbolMeta?.declarations

if (!baseLocations) {
if (aliasSymbolDeclarations) {
baseDeclarations.push(...aliasSymbolDeclarations)
}

if (info.symbolMeta?.declarations && baseDeclarations.length === 0) {
baseDeclarations.push(...info.symbolMeta.declarations)
}

const baseLocations = baseDeclarations.map(({ location }) => location)

if (isEmpty(baseLocations)) {
if (info.kind === "function" && info.signatures.length === 1) {
return wrapSafe(getLocations)(info.signatures[0].symbolMeta)
}
Expand All @@ -567,5 +584,7 @@ function getTypeLocations(info: TypeInfo): SourceFileLocation[] | undefined {
}

function getLocations(info: SymbolInfo): SourceFileLocation[] | undefined {
return info.declarations?.map(({ location }) => location)
return (info.resolvedDeclarations ?? info.declarations)?.map(
({ location }) => location
)
}
15 changes: 15 additions & 0 deletions packages/api/src/tree.ts
Expand Up @@ -60,6 +60,7 @@ import {
isNamespace,
getSignaturesOfType,
isClassOrInterfaceType,
getAliasedSymbol,
} from "./util"

const maxDepthExceeded: TypeInfo = { kind: "max_depth", id: getEmptyTypeId() }
Expand Down Expand Up @@ -699,6 +700,8 @@ function _generateTypeTree(
isAnonymous = false,
options: TypeTreeOptions = {}
): SymbolInfo {
const aliasedSymbol = getAliasedSymbol(tsCtx, symbol)

const parameterInfo = getParameterInfo(tsCtx, symbol)

const optional = options.optional ?? parameterInfo.optional
Expand All @@ -714,6 +717,17 @@ function _generateTypeTree(
symbol.getDeclarations()?.map(getDeclarationInfo)
)

const resolvedDeclarations =
aliasedSymbol &&
aliasedSymbol !== symbol &&
isNonEmpty(aliasedSymbol.declarations)
? wrapSafe(filterUndefined)(
aliasedSymbol
.getDeclarations()
?.map(getDeclarationInfo)
)
: undefined

const isReadonly = isReadonlySymbol(tsCtx, symbol)

return {
Expand All @@ -725,6 +739,7 @@ function _generateTypeTree(
...(rest && { rest: true }),
...(insideClassOrInterface && { insideClassOrInterface: true }),
...(declarations && { declarations }),
...(resolvedDeclarations && { resolvedDeclarations }),
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/api/src/types.ts
Expand Up @@ -69,6 +69,7 @@ export type SymbolInfo = {
readonly?: boolean
insideClassOrInterface?: boolean
declarations?: DeclarationInfo[]
resolvedDeclarations?: DeclarationInfo[]
}

export type IndexInfo = {
Expand Down
11 changes: 10 additions & 1 deletion packages/api/src/util.ts
@@ -1,6 +1,6 @@
import assert = require("assert")
import nodeTest from "node:test"
import type * as ts from "typescript"
import * as ts from "typescript"
import {
wrapSafe,
isEmpty,
Expand Down Expand Up @@ -944,6 +944,15 @@ export function isReadonlySymbol(
)
}

export function getAliasedSymbol(
{ typeChecker }: TypescriptContext,
symbol: ts.Symbol
) {
if (!(symbol.flags & ts.SymbolFlags.Alias)) return undefined

return typeChecker.getAliasedSymbol(symbol)
}

export function getSymbolExports(symbol: ts.Symbol): ts.Symbol[] {
const result: ts.Symbol[] = []

Expand Down
20 changes: 10 additions & 10 deletions tests/baselines/reference/module.localized.tree
Expand Up @@ -12,31 +12,31 @@ import { c } from "./moduleExport"
"name": "c",
"locations": [
{
"fileName": "cases/module.ts",
"fileName": "/Users/maxstoumen/Projects/ts-type-explorer/tests/cases/moduleExport.ts",
"range": {
"start": {
"line": 0,
"character": 9
"line": 3,
"character": 17
},
"end": {
"line": 0,
"character": 10
"line": 3,
"character": 18
}
}
}
]
},
"locations": [
{
"fileName": "cases/module.ts",
"fileName": "/Users/maxstoumen/Projects/ts-type-explorer/tests/cases/moduleExport.ts",
"range": {
"start": {
"line": 0,
"character": 9
"line": 3,
"character": 17
},
"end": {
"line": 0,
"character": 10
"line": 3,
"character": 18
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions tests/baselines/reference/module.tree
Expand Up @@ -54,6 +54,23 @@ import { c } from "./moduleExport"
}
}
}
],
"resolvedDeclarations": [
{
"location": {
"fileName": "/Users/maxstoumen/Projects/ts-type-explorer/tests/cases/moduleExport.ts",
"range": {
"start": {
"line": 3,
"character": 17
},
"end": {
"line": 3,
"character": 18
}
}
}
}
]
},
"id": "0"
Expand Down
10 changes: 10 additions & 0 deletions tests/other/intersectionComponent.spec.ts
Expand Up @@ -34,4 +34,14 @@ describe("intersectionComponent.tsx", () => {
assert(param.kind === "object")
assert(param.symbolMeta?.name === "event")
})

it("has declaration locations", () => {
const ctx = createTsContext(fileName)
const pos = { line: 4, character: 8 }

const info = getTypeInfoAtRange(ctx, {
fileName,
range: { start: pos, end: pos },
})
})
})

0 comments on commit 4d6640f

Please sign in to comment.