uqbar-project / wollok-lsp-ide

IDE for Wollok - LSP node-based
GNU General Public License v3.0
7 stars 3 forks source link

Mover funciones de definitions.ts a wollok-ts #162

Closed fdodino closed 1 month ago

fdodino commented 7 months ago

Hoy tenemos toda esta funcionalidad que parece que podría migrarse toda a wollok-ts:

// WOLLOK-TS: hablar con Nahue/Ivo, para mí desde acá para abajo todo se podria migrar a wollok-ts
export const getNodeDefinition = (environment: Environment) => (node: Node): Node[] => {
  try {
    return match(node)(
      when(Reference)(node => definedOrEmpty(referenceDefinition(node))),
      when(Send)(sendDefinitions(environment)),
      when(Super)(node => definedOrEmpty(superMethodDefinition(node))),
      when(Self)(node => definedOrEmpty(node.ancestors.find(is(Module))))
    )
  } catch (error) {
    logger.error(`✘ Error in getNodeDefinition: ${error}`, error)
    return [node]
  }
}

function referenceDefinition(ref: Reference<Node>): Node | undefined {
  return ref.target
}

const sendDefinitions = (environment: Environment) => (send: Send): Method[] => {
  try {
    return match(send.receiver)(
      when(Reference)(node => {
        const target = node.target
        return target && is(Singleton)(target) ?
          definedOrEmpty(target.lookupMethod(send.message, send.args.length))
          : allMethodDefinitions(environment, send)
      }),
      when(New)(node => definedOrEmpty(node.instantiated.target?.lookupMethod(send.message, send.args.length))),
      when(Self)(_ => moduleFinderWithBackup(environment, send)(
        (module) => definedOrEmpty(module.lookupMethod(send.message, send.args.length))
      )),
    )
  } catch (error) {
    logger.error(`✘ Send definitions error: ${error}`, error)
    return allMethodDefinitions(environment, send)
  }
}

function superMethodDefinition(superNode: Super): Method | undefined {
  const currentMethod = superNode.ancestors.find(is(Method))!
  const module = superNode.ancestors.find(is(Module))
  return module ? module.lookupMethod(currentMethod.name, superNode.args.length, { lookupStartFQN: module.fullyQualifiedName }) : undefined
}

function allMethodDefinitions(environment: Environment, send: Send): Method[] {
  const arity = send.args.length
  const name = send.message
  return environment.descendants.filter(n =>
    is(Method)(n) &&
    n.name === name &&
    n.parameters.length === arity
  ) as Method[]
}

// UTILS
const moduleFinderWithBackup = (environment: Environment, send: Send) => (methodFinder: (module: Module) => Method[]) => {
  const module = send.ancestors.find(is(Module))
  return module ? methodFinder(module) : allMethodDefinitions(environment, send)
}

function definedOrEmpty<T>(value: T | undefined): T[] {
  return value ? [value] : []
}
fdodino commented 6 months ago

Update, se migraron algunas, quedó pendiente ésto:

// TODO: terminar de migrar a wollok-ts estas 4 definiciones
export const getNodeDefinition = (environment: Environment) => (node: Node): Node[] => {
  try {
    return match(node)(
      when(Reference)(node => definedOrEmpty(node.target)),
      when(Send)(sendDefinitions(environment)),
      when(Super)(node => definedOrEmpty(superMethodDefinition(node))),
      when(Self)(node => definedOrEmpty(getParentModule(node)))
    )
  } catch {
    return [node]
  }
}

const superMethodDefinition = (superNode: Super): Method | undefined => {
  const currentMethod = superNode.ancestors.find(is(Method))!
  const module = getParentModule(superNode)
  return module ? module.lookupMethod(currentMethod.name, superNode.args.length, { lookupStartFQN: module.fullyQualifiedName }) : undefined
}

const getParentModule = (node: Node) => node.ancestors.find(is(Module))

const definedOrEmpty = <T>(value: T | undefined): T[] => value ? [value] : []