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

test: testing java method snippet arguments (related to flix/flix#8255) #440

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ By adding your name to this document, you agree to release all your contribution
- [Magnus Holm Rasmussen](https://github.com/mR4smussen)
- [Holger Dal Mogensen](https://github.com/sockmaster27)
- [Jakob Schneider Villumsen](https://github.com/jaschdoc)
- [Alexander Dybdahl Troelsen](https://github.com/LoZander)

72 changes: 71 additions & 1 deletion test/src/completions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,53 @@

import * as assert from 'assert'
import * as vscode from 'vscode'
import { getTestDocUri, init, open, typeText, addFile } from './util'
import { getTestDocUri, init, open, typeText, addFile, deleteFile, copyFile } from './util'

suite('Completions', () => {
const docUri = getTestDocUri('src/Temp.flix')
let tempDocUri: vscode.Uri | null = null

suiteSetup(async () => {
await init('completions')
})

teardown(async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this? Is it necessary? I don't believe we do this for other tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I modelled this after how it was done in the diagnostics suite. We specifically want there to only be one file in src at a time (even within the same suite), because the error produced by the unfinished line in one file can prevent any suggestions from appearing in the other. I at least know that some interference between tests is happening, and I assume this is it. For instance, when testing for completion suggests in JavaMath, if JavaStringBuilder also exists in src, the test fails. I suppose that is also an error worth addressing, since the suggestions should work either way, but it feels tangential to the issue I wanted to test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, sorry, I missed that you asked what it was. I saw this done in the diagnostics suite, as I said. From context, I assume this is run at the end of each test. This way, the src folder is always clean upon the start of a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I suppose I could move it to the inner test suite, since it's only relevant there

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sockmaster27 proposed looking towards the diagnostics suite, so he can probably tell whether I've understood the trick used there and if I've applied it correctly here :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe its OK. I am not super familiar with the codebase. Lets see what Holger says.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am always paranoid about deleteFile :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, ofc. Tbh, it didn't occur to me before, but I can understand your paranoia. If it's not necessary, it's ofc. best to avoid :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is perfectly in line with the way it's done in diagnostics.
In files.test.ts I've done more or less the same thing by (admittedly inconsistently) running init() in setup() instead of suiteSetup() to hard reset the contents of the entire workspace before each test. I suppose this is the more declarative way to handle it, but it's not super important to me either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, good to hear. I wouldn't mind changing it to the files.test.ts approach though, if you think it's preferable :)

if (tempDocUri !== null) {
await deleteFile(tempDocUri)
}
})

/**
* Determines if there is a completion suggestion at the `cursor` in the file `src/fileName`.
*
* @param fileName name of flix file we're testing. Must include the `.flix` extension.
* @param cursor the position of the cursor.
* @param predicate the predicate by which we determine if a completion is valid.
* @returns `true` if there is a completion suggestion at `cursor` which satisfies `predicate`.
*/
async function validCompletionExists(
fileName: string,
cursor: vscode.Position,
predicate: (item: vscode.CompletionItem) => boolean,
): Promise<boolean> {
// Setup file
const latentUri = getTestDocUri(`latent/${fileName}`)
const srcUri = getTestDocUri(`src/${fileName}`)

tempDocUri = srcUri
await copyFile(latentUri, srcUri)

await open(srcUri)

const r = await vscode.commands.executeCommand<vscode.CompletionList>(
'vscode.executeCompletionItemProvider',
srcUri,
cursor,
)

return r.items.some(predicate)
}

test('Should propose completing mod', async () => {
await addFile(docUri, '')
await open(docUri)
Expand All @@ -42,4 +80,36 @@ suite('Completions', () => {
true,
)
})

suite('Java Methods', () => {
test('Should complete Java static method', async () => {
const cursor = new vscode.Position(5 - 1, 23 - 1)
const pred = item => item.label === 'floor(arg0: double): double \\ IO'
assert.strictEqual(await validCompletionExists('JavaMath.flix', cursor, pred), true)
})

test('Should complete Java method with snippet placeholder arg for static method', async () => {
const cursor = new vscode.Position(5 - 1, 23 - 1)
const pred = item => (item.insertText as vscode.SnippetString).value === 'floor(${1:arg0})'
assert.strictEqual(await validCompletionExists('JavaMath.flix', cursor, pred), true)
})

test('Should complete Java method with snippet placeholder args for static method', async () => {
const cursor = new vscode.Position(9 - 1, 23 - 1)
const pred = item => (item.insertText as vscode.SnippetString).value === 'max(${1:arg0}, ${2:arg1})'
assert.strictEqual(await validCompletionExists('JavaMath.flix', cursor, pred), true)
})

test('Should complete Java non-static method', async () => {
const cursor = new vscode.Position(8 - 1, 18 - 1)
const pred = item => item.label === 'append(arg0: String): StringBuilder \\ IO'
assert.strictEqual(await validCompletionExists('JavaStringBuilder.flix', cursor, pred), true)
})

test('Should complete Java method with snipper placeholder arg for non-static method', async () => {
const cursor = new vscode.Position(8 - 1, 18 - 1)
const pred = item => (item.insertText as vscode.SnippetString).value === 'append(${1:arg0})'
assert.strictEqual(await validCompletionExists('JavaStringBuilder.flix', cursor, pred), true)
})
})
})
11 changes: 11 additions & 0 deletions test/testWorkspaces/completions/latent/JavaMath.flix
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mod JavaMath {
import java.lang.Math;

pub def floor(x: Float64): Float64 \ IO =
let r = Math.f
r

pub def max(x: Float64): Float64 \ IO =
let r = Math.m
r
}
12 changes: 12 additions & 0 deletions test/testWorkspaces/completions/latent/JavaStringBuilder.flix
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mod JavaStringBuilder {
import java.lang.StringBuilder;

pub def create(): StringBuilder \ IO =
new StringBuilder()

pub def append(s: String, builder: StringBuilder): StringBuilder \ IO =
builder.a

pub def toString(builder: StringBuilder): String \ IO =
builder.toString()
}
Loading