Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: don't load source files outside of the relevant paths #313

Merged
merged 12 commits into from
Jan 30, 2024
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"json.schemaDownload.enable": true,
"eslint.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"editor.detectIndentation": false,
"editor.formatOnSave": true,
Expand Down
5 changes: 4 additions & 1 deletion client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ let tomlWatcher: vscode.FileSystemWatcher

const extensionObject = vscode.extensions.getExtension('flix.flix')

export const FLIX_GLOB_PATTERN = '**/*.flix'
export const FLIX_GLOB_PATTERN = new vscode.RelativePattern(
vscode.workspace.workspaceFolders?.[0],
'{*.flix,src/**/*.flix,test/**/*.flix}',
)

export const FPKG_GLOB_PATTERN = new vscode.RelativePattern(vscode.workspace.workspaceFolders?.[0], 'lib/**/*.fpkg')
export const JAR_GLOB_PATTERN = new vscode.RelativePattern(vscode.workspace.workspaceFolders?.[0], 'lib/**/*.jar')
Expand Down
40 changes: 36 additions & 4 deletions server/src/engine/flix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface StartEngineInput {
let flixInstance: ChildProcess | undefined = undefined
let startEngineInput: StartEngineInput
let flixRunning: boolean = false
let currentWorkspaceFiles: Set<string> = new Set()

export function isRunning() {
return flixRunning
Expand All @@ -75,10 +76,6 @@ export function getExtensionVersion() {
return _.get(startEngineInput, 'extensionVersion', '(unknown version)')
}

export function getProjectRootUri() {
return _.first(startEngineInput.workspaceFolders)
}

export function updateUserConfiguration(userConfiguration: UserConfiguration) {
_.set(userConfiguration, 'userConfiguration', startEngineInput)
queue.resetEnqueueDebounced()
Expand Down Expand Up @@ -106,6 +103,8 @@ export async function start(input: StartEngineInput) {

const { flixFilename, extensionPath, workspaceFiles, workspacePkgs, workspaceJars } = input

currentWorkspaceFiles = new Set(workspaceFiles)

// Check for valid Java version
const { majorVersion, versionString } = await javaVersion(extensionPath)
if (versionString === undefined) {
Expand Down Expand Up @@ -202,15 +201,48 @@ export async function stop() {
}
}

/**
* Add the given `uri` to the workspace.
*/
export function addUri(uri: string) {
currentWorkspaceFiles.add(uri)

const job: jobs.Job = {
request: jobs.Request.apiAddUri,
uri,
}
queue.enqueue(job)
}

/**
* Handle a change in the file with the given `uri`.
*
* If this URI has not already been added to the workspace via {@linkcode addUri},
* it will be ignored, making it safe to call this function on any file.
*/
export function updateUri(uri: string, src: string) {
if (!currentWorkspaceFiles.has(uri)) {
magnus-madsen marked this conversation as resolved.
Show resolved Hide resolved
return
}

// Including the source code in the job is necessary because the file might not yet have been saved
const job: jobs.Job = {
request: jobs.Request.apiAddUri,
uri,
src,
}

// Skip the delay to make auto-complete work
const skipDelay = true
queue.enqueue(job, skipDelay)
}

/**
* Remove the given `uri` from the workspace.
*/
export function remUri(uri: string) {
currentWorkspaceFiles.delete(uri)

const job: jobs.Job = {
request: jobs.Request.apiRemUri,
uri,
Expand Down
29 changes: 11 additions & 18 deletions server/src/handlers/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,21 @@ import {
InitializeParams,
InitializeResult,
InlayHintParams,
ServerRequestHandler,
TextDocumentChangeEvent,
TextDocumentSyncKind,
} from 'vscode-languageserver'
import { TextDocument } from 'vscode-languageserver-textdocument'

import * as jobs from '../engine/jobs'
import * as queue from '../engine/queue'
import * as engine from '../engine'
import * as socket from '../engine/socket'

import { clearDiagnostics, sendDiagnostics, sendNotification } from '../server'
import { makePositionalHandler, makeEnqueuePromise, enqueueUnlessHasErrors, makeDefaultResponseHandler } from './util'
import { getProjectRootUri } from '../engine'
import { USER_MESSAGE } from '../util/userMessages'
import { StatusCode } from '../util/statusCodes'

const _ = require('lodash/fp')
import _ = require('lodash/fp')

interface UriInput {
uri: string
Expand Down Expand Up @@ -153,28 +151,20 @@ export function handleExit() {
engine.stop()
}

export function handleSave(params: any) {
export function handleSave(params: TextDocumentChangeEvent<TextDocument>) {
if (engine.compileOnSaveEnabled()) {
addUriToCompiler(params.document, true)
const document = params.document
engine.updateUri(document.uri, document.getText())
}
}

export function handleChangeContent(params: any) {
export function handleChangeContent(params: TextDocumentChangeEvent<TextDocument>) {
if (engine.compileOnChangeEnabled()) {
// We send the document immediately to ensure better auto-complete.
addUriToCompiler(params.document, true)
const document = params.document
engine.updateUri(document.uri, document.getText())
}
}

function addUriToCompiler(document: TextDocument, skipDelay?: boolean) {
const job: jobs.Job = {
request: jobs.Request.apiAddUri,
uri: document.uri, // Note: this typically has the file:// scheme (important for files as keys)
src: document.getText(),
}
queue.enqueue(job, skipDelay)
}

/**
* @function
*/
Expand Down Expand Up @@ -381,6 +371,9 @@ function makeVersionResponseHandler(promiseResolver: () => void) {
export function lspCheckResponseHandler({ status, result }: socket.FlixResponse) {
clearDiagnostics()
sendNotification(jobs.Request.internalDiagnostics, { status, result })

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

Expand Down
5 changes: 5 additions & 0 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { createConnection, TextDocuments, ProposedFeatures, PublishDiagnosticsPa

import { TextDocument } from 'vscode-languageserver-textdocument'

// Workaround for circular dependency between flix.ts and queue.ts
// TODO: Fix this
import * as queue from './engine/queue'
queue

import * as handlers from './handlers'
import * as jobs from './engine/jobs'

Expand Down
Loading