Skip to content

Commit

Permalink
refactor: make response types more granular
Browse files Browse the repository at this point in the history
  • Loading branch information
sockmaster27 committed Jan 30, 2024
1 parent 8330083 commit d14e533
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 29 deletions.
67 changes: 56 additions & 11 deletions server/src/engine/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { StatusCode } from '../util/statusCodes'

const _ = require('lodash/fp')
const WebSocket = require('ws')
import { DiagnosticSeverity, DiagnosticTag } from 'vscode-languageserver'

let webSocket: any
let webSocketOpen = false
Expand All @@ -39,7 +40,7 @@ interface sentMessagesMap {
const sentMessagesMap: sentMessagesMap = {}
const MESSAGE_TIMEOUT_SECONDS = 30

export interface FlixResult {
export interface FlixResultCheck {
uri: string
diagnostics: [
{
Expand All @@ -53,20 +54,62 @@ export interface FlixResult {
character: number
}
}
severity: number
severity: DiagnosticSeverity
code: string
message: string
tags: string[]
tags: DiagnosticTag[]
},
]
reportPath: string
}
/**
* The general result of a job
*/
export interface FlixResult {
targetUri?: string
}

export interface FlixResponse {
/**
* The jobs that can be assumed to never produce an invalid request
*/
type InfallibleJobs = jobs.Request.lspCheck

interface FlixResponseBase {
id: string
status: StatusCode
}
export interface FlixResponseCompilerError extends FlixResponseBase {
jobRequest: jobs.Request
status: StatusCode.CompilerError
result: {
reportPath: string
}
}
/**
* The special case of lsp/check, which is handled differently from the rest
*/
export interface FlixResponseCheck extends FlixResponseBase {
jobRequest: jobs.Request.lspCheck
status: StatusCode.Success
result: FlixResultCheck[]
}
export interface FlixResponseSuccess extends FlixResponseBase {
jobRequest: Exclude<jobs.Request, jobs.Request.lspCheck>
status: StatusCode.Success
result?: FlixResult
}
export interface FlixResponseInvalidRequest extends FlixResponseBase {
jobRequest: Exclude<jobs.Request, InfallibleJobs>
status: StatusCode.InvalidRequest
message: string
}
type FlixResponseUnknown =
| FlixResponseCompilerError
| FlixResponseCheck
| FlixResponseSuccess
| FlixResponseInvalidRequest
/**
* The types of responses observable by a normal job on the queue
*/
export type FlixResponse = FlixResponseSuccess | FlixResponseInvalidRequest

interface InitialiseSocketInput {
uri: string
Expand Down Expand Up @@ -112,10 +155,12 @@ export function initialiseSocket({ uri, onOpen, onClose }: InitialiseSocketInput
})

webSocket.on('message', (data: string) => {
const flixResponse: FlixResponse = JSON.parse(data)
const job: jobs.EnqueuedJob = jobs.getJob(flixResponse.id)
// Parse response and add the associated jobRequest to the object
const rawResponse: Omit<FlixResponseUnknown, 'jobRequest'> = JSON.parse(data)
const job: jobs.EnqueuedJob = jobs.getJob(rawResponse.id)
const flixResponse = { ...rawResponse, jobRequest: job.request } as FlixResponseUnknown

handleResponse(flixResponse, job)
handleResponse(flixResponse)
})
}

Expand Down Expand Up @@ -196,11 +241,11 @@ export function sendMessage(job: jobs.EnqueuedJob, retries = 0) {
webSocket.send(JSON.stringify(job))
}

function handleResponse(flixResponse: FlixResponse, job: jobs.EnqueuedJob) {
function handleResponse(flixResponse: FlixResponseUnknown) {
if (flixResponse.status === StatusCode.CompilerError) {
clearDiagnostics()
handleCrash(flixResponse)
} else if (job.request === jobs.Request.lspCheck) {
} else if (flixResponse.jobRequest === jobs.Request.lspCheck) {
lspCheckResponseHandler(flixResponse)
} else {
eventEmitter.emit(flixResponse.id, flixResponse)
Expand Down
28 changes: 14 additions & 14 deletions server/src/handlers/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,13 @@ export const handleGotoDefinition = makePositionalHandler(
)

function makeGotoDefinitionResponseHandler(promiseResolver: (result?: socket.FlixResult) => void) {
return function responseHandler({ status, result }: socket.FlixResponse) {
const targetUri = _.get('targetUri', result)
if (status === StatusCode.Success) {
if (_.startsWith('file://', targetUri)) {
return promiseResolver(result)
return function responseHandler(response: socket.FlixResponse) {
if (response.status === StatusCode.Success) {
const targetUri = response.result?.targetUri
if (targetUri !== undefined && _.startsWith('file://', targetUri)) {
return promiseResolver(response.result)
} else {
sendNotification(jobs.Request.internalMessage, USER_MESSAGE.FILE_NOT_AVAILABLE(targetUri))
sendNotification(jobs.Request.internalMessage, USER_MESSAGE.FILE_NOT_AVAILABLE(targetUri ?? 'undefined'))
}
}
promiseResolver()
Expand Down Expand Up @@ -315,20 +315,20 @@ function makeVersionResponseHandler(promiseResolver: () => void) {
*
* This is different from the rest of the response handlers in that it isn't tied together with its enqueueing function.
*/
export function lspCheckResponseHandler({ status, result }: socket.FlixResponse) {
export function lspCheckResponseHandler(response: socket.FlixResponseCheck) {
clearDiagnostics()
sendNotification(jobs.Request.internalDiagnostics, { status, result })
sendNotification(jobs.Request.internalDiagnostics, response)

// TODO: Find out why TS doen't like this
// @ts-ignore
_.each(sendDiagnostics, result)
for (const r of response.result) {
sendDiagnostics(r)
}
}

/**
* Handle response where status is `statusCodes.COMPILER_ERROR`
* Handle response where status is `StatusCode.CompilerError`
*/
export function handleCrash({ status, result }: socket.FlixResponse) {
const path = result?.reportPath as string
export function handleCrash(response: socket.FlixResponseCompilerError) {
const path = response.result.reportPath
sendNotification(jobs.Request.internalError, {
message: USER_MESSAGE.COMPILER_CRASHED(path),
actions: [
Expand Down
8 changes: 4 additions & 4 deletions server/src/handlers/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import * as socket from '../engine/socket'
import { hasErrors } from '../server'
import { StatusCode } from '../util/statusCodes'

type ResponseHandler = ({ status, result }: socket.FlixResponse) => void
type ResponseHandler = (response: socket.FlixResponse) => void

export function makeDefaultResponseHandler(promiseResolver: (result?: socket.FlixResult) => void): ResponseHandler {
return function responseHandler({ status, result }: socket.FlixResponse) {
if (status === StatusCode.Success) {
promiseResolver(result)
return function responseHandler(response: socket.FlixResponse) {
if (response.status === StatusCode.Success) {
promiseResolver(response.result)
} else {
promiseResolver()
}
Expand Down

0 comments on commit d14e533

Please sign in to comment.