QuickCheck Not Working
Hi,
The QuickCheck button does not seem to be working as it should. In particular whenever I click it, I get the following VS error message: VS Code can't execute this file. Check the terminal. In the terminal, I see type c:\Users\%USER%\.vscode\extensions\ucl.haskelly-0.5.4\ad39fbca-d904-42a7-92bf-b7e66c5a895a.txt -------- Error -------- Error: ENOENT: no such file or directory, open 'c:\Users\%USER%\Documents\e49dcfb1-2bb0-4677-9758-d82bee8cb210.hs'------------------------
I got annoyed by the QuickCheck button not working so I decided to fix it. Here is my solution (tested on Windows 10, fully modified file is attached at the end of the post):
- We need to modify testCode.js file in Haskelly installation directory (in my case the file was located at C:\Users\YourUsername\.vscode\extensions\ucl.haskelly-0.5.5\out\src\helpers\testCode.js). Open it in a text editor.
- There is a bug in testHaskellFile function. In case of a non-stack project we want to create a copy of the original haskell source code, remove main function from it and add code that runs the tests. The original code asynchronously creates the copy and reads from it. We want to start reading AFTER the copy is finished. Replace line 136
fs.createReadStream(filePath).pipe(fs.createWriteStream(newPath));with this
let writer = fs.createWriteStream(newPath);
fs.createReadStream(filePath).pipe(writer);
then place the reading code inside this
writer.once('finish', () => {
//here goes the reading
fs.readFile(newPath...
});
This way we ensure that we read the file once we finished copying. 3. There is also a problem with main function removal part. The original code expects the main function to be at the end of a source code file and that there will be no main function type declaration. Here is my improved version of removeMainFunction function:
function removeMultilineComments(data) {
return data.replace(/{-[\s\S]*?-}/g, (comment) => {
return comment.replace(/\S/g, ' ');
});
}
function removeMainFunction(data) {
const main_decl_regex = /^main\s*::.*$/m;
const main_def_regex = /^main\s*=.*$/m;
const comment_regex = /^\s*--.*$/m;
const other_regex = /^\S+.*$/m;
const dataArray = removeMultilineComments(data).split('\n');
let decl_start;
let decl_end;
let def_start;
let def_end;
for (let i = 0; i < dataArray.length; i++) {
//main type signature
if (main_decl_regex.test(dataArray[i])) {
if (def_start !== undefined && def_end === undefined) {
def_end = i;
}
if (decl_start === undefined) {
decl_start = i;
}
}
//main definition
else if (main_def_regex.test(dataArray[i])) {
if (decl_start !== undefined && decl_end === undefined) {
decl_end = i;
}
if (def_start === undefined) {
def_start = i;
}
}
//skip comments
else if (comment_regex.test(dataArray[i])) {
//do nothing
}
//different expression/declaration
else if (other_regex.test(dataArray[i])) {
if (decl_start !== undefined && decl_end === undefined) {
decl_end = i;
}
if (def_start !== undefined && def_end === undefined) {
def_end = i;
}
}
}
if (decl_start !== undefined && decl_end === undefined) {
decl_end = dataArray.length;
}
if (def_start !== undefined && def_end === undefined) {
def_end = dataArray.length;
}
return dataArray.filter((value, index, arr) => {
return (decl_start === undefined || index < decl_start || index >= decl_end) &&
(def_start === undefined || index < def_start || index >= def_end);
}).join('\n');
}
That's it. Worked for me. You can find modified testCode.js here (it's packed as .zip): testCode.zip
Hello @maxez, thanks a lot for your contribution! Would you mind opening a PR with your change so that your contribution is recorded and I can formally merge it? Thanks again!
Hi @martrik. I created the PR with my changes (I modified testCode.ts file from which I guess the testCode.js is generated). Please verify it since I'm not a JS programmer.