Skip to content

Commit

Permalink
feat: support modules and namespaces
Browse files Browse the repository at this point in the history
closes #6
closes #7
  • Loading branch information
mxsdev committed Nov 3, 2022
1 parent 5848029 commit 670e069
Show file tree
Hide file tree
Showing 15 changed files with 1,161 additions and 3 deletions.
2 changes: 2 additions & 0 deletions packages/api/src/localization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const KindText: Record<
interface: "interface",
method: "method",
jsx_component: "component",
namespace: "namespace",
module: "module",
}

export function getKindText(
Expand Down
5 changes: 5 additions & 0 deletions packages/api/src/localizedTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ function getChildren(
return getLocalizedTypeParameter(info, typeArgument)
}

case "module":
case "namespace": {
return info.exports.map(localize)
}

default: {
return undefined
}
Expand Down
19 changes: 18 additions & 1 deletion packages/api/src/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ import {
isReadonlySymbol,
isReadonlyArrayType,
isReadonlyTupleType,
getSymbolExports,
isNamespace,
} from "./util"

const maxDepthExceeded: TypeInfo = { kind: "max_depth", id: getEmptyTypeId() }
Expand Down Expand Up @@ -96,6 +98,8 @@ function _generateTypeTree(
type = getSymbolType(tsCtx, symbol!)
}

const typeSymbol = type.symbol as ts.Symbol | undefined

let isAnonymousSymbol = !symbol

if (!symbol) {
Expand Down Expand Up @@ -226,6 +230,15 @@ function _generateTypeTree(
return typeInfoId

function createNode(type: ts.Type): TypeInfoNoId {
for (const s of [symbol, typeSymbol]) {
if (s && s.flags & ts.SymbolFlags.Module) {
return {
kind: isNamespace(tsCtx, s) ? "namespace" : "module",
exports: parseSymbols(getSymbolExports(s)),
}
}
}

const flags = type.getFlags()

if (flags & ts.TypeFlags.TypeParameter) {
Expand Down Expand Up @@ -316,7 +329,6 @@ function _generateTypeTree(
value: (type as ts.BigIntLiteralType).value,
}
} else if (flags & ts.TypeFlags.Object) {
const { symbol: typeSymbol } = type
if (typeSymbol && typeSymbol.flags & SymbolFlags.Enum) {
return {
kind: "enum",
Expand Down Expand Up @@ -827,6 +839,11 @@ export function getTypeInfoChildren(info: TypeInfo): TypeInfo[] {
case "string_mapping": {
return [info.type]
}

case "module":
case "namespace": {
return [...info.exports]
}
}

return []
Expand Down
8 changes: 8 additions & 0 deletions packages/api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ export type TypeInfoNoId = {
| {
kind: "max_depth"
}
| {
kind: "namespace"
exports: TypeInfo[]
}
| {
kind: "module"
exports: TypeInfo[]
}
)

export type TypeId = string
Expand Down
45 changes: 43 additions & 2 deletions packages/api/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ export function getSignatureTypeArguments(
)
?.typeArguments?.map((t) =>
getTypeFromTypeNode(ctx, t, enclosingDeclaration)
)
) // TODO: error here...
}

export function getDescendantAtPosition(
Expand Down Expand Up @@ -846,7 +846,7 @@ export function getSymbolOrTypeOfNode(
if (symbol) {
const symbolType = getSymbolType(ctx, symbol, node)

if (isValidType(symbolType)) {
if (isValidType(symbolType) || symbol.flags & ts.SymbolFlags.Module) {
return { symbol, node }
}
}
Expand Down Expand Up @@ -922,3 +922,44 @@ export function isReadonlySymbol(
// some(symbol.declarations, isReadonlyAssignmentDeclaration)
)
}

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

symbol.exports?.forEach((value) => result.push(value))
symbol.globalExports?.forEach((value) => result.push(value))

return result
}

export function isNamespace(
{ ts }: TypescriptContext,
symbol: ts.Symbol
): boolean {
const declaration = getDeclarationOfKind<ts.ModuleDeclaration>(
symbol,
ts.SyntaxKind.ModuleDeclaration
)
const isNamespace =
declaration &&
declaration.name &&
declaration.name.kind === ts.SyntaxKind.Identifier

return !!isNamespace
}

function getDeclarationOfKind<T extends ts.Declaration>(
symbol: ts.Symbol,
kind: T["kind"]
): T | undefined {
const declarations = symbol.declarations
if (declarations) {
for (const declaration of declarations) {
if (declaration.kind === kind) {
return declaration as T
}
}
}

return undefined
}
8 changes: 8 additions & 0 deletions packages/typescript-explorer-vscode/src/view/typeTreeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,14 @@ function getMeta(info: LocalizedTypeInfo, depth: number): TypeTreeItemMeta {
return ["symbol-interface"]
}

case "namespace": {
return ["symbol-namespace"]
}

case "module": {
return ["symbol-module"]
}

case "class": {
return ["symbol-class"]
}
Expand Down

0 comments on commit 670e069

Please sign in to comment.