UNPKG

jsdoc-type-pratt-parser

Version:

[![Npm Package](https://badgen.net/npm/v/jsdoc-type-pratt-parser)](https://www.npmjs.com/package/jsdoc-type-pratt-parser) [![Test Status](https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/actions/workflows/test.yml/badge.svg?branch=main)]

93 lines (80 loc) 3.19 kB
import { composeParslet, type ParsletFunction } from './Parslet.js' import { Precedence } from '../Precedence.js' import type { FunctionResult, RootResult } from '../result/RootResult.js' import type { IntermediateResult } from '../result/IntermediateResult.js' import type { KeyValueResult, NonRootResult } from '../result/NonRootResult.js' import { UnexpectedTypeError } from '../errors.js' import { assertPlainKeyValueOrRootResult } from '../assertTypes.js' export function getParameters (value: IntermediateResult): Array<RootResult | KeyValueResult> { let parameters: NonRootResult[] = [] if (value.type === 'JsdocTypeParameterList') { parameters = value.elements } else if (value.type === 'JsdocTypeParenthesis') { parameters = [value.element] } else { throw new UnexpectedTypeError(value) } return parameters.map(p => assertPlainKeyValueOrRootResult(p)) } export function getUnnamedParameters (value: IntermediateResult): RootResult[] { const parameters = getParameters(value) if (parameters.some(p => p.type === 'JsdocTypeKeyValue')) { throw new Error('No parameter should be named') } return parameters as RootResult[] } export function createFunctionParslet ({ allowNamedParameters, allowNoReturnType, allowWithoutParenthesis, allowNewAsFunctionKeyword }: { allowNamedParameters?: string[] allowWithoutParenthesis: boolean allowNoReturnType: boolean allowNewAsFunctionKeyword: boolean }): ParsletFunction { return composeParslet({ name: 'functionParslet', accept: (type, next) => type === 'function' || (allowNewAsFunctionKeyword && type === 'new' && next === '('), parsePrefix: parser => { const newKeyword = parser.consume('new') parser.consume('function') const hasParenthesis = parser.lexer.current.type === '(' if (!hasParenthesis) { if (!allowWithoutParenthesis) { throw new Error('function is missing parameter list') } return { type: 'JsdocTypeName', value: 'function' } } let result: FunctionResult = { type: 'JsdocTypeFunction', parameters: [], arrow: false, constructor: newKeyword, parenthesis: hasParenthesis } const value = parser.parseIntermediateType(Precedence.FUNCTION) if (allowNamedParameters === undefined) { result.parameters = getUnnamedParameters(value) } else if (newKeyword && value.type === 'JsdocTypeFunction' && value.arrow) { result = value result.constructor = true return result } else { result.parameters = getParameters(value) for (const p of result.parameters) { if (p.type === 'JsdocTypeKeyValue' && (!allowNamedParameters.includes(p.key))) { throw new Error(`only allowed named parameters are ${allowNamedParameters.join(', ')} but got ${p.type}`) } } } if (parser.consume(':')) { result.returnType = parser.parseType(Precedence.PREFIX) } else { if (!allowNoReturnType) { throw new Error('function is missing return type') } } return result } }) }