Skip to content

Commit

Permalink
Support codeactions at the edges of tokens. (#642)
Browse files Browse the repository at this point in the history
  • Loading branch information
TwitchBronBron authored Jul 15, 2022
1 parent d175c88 commit c33d9c0
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ export class Program {
//only keep diagnostics related to this file
.filter(x => x.file === file)
//only keep diagnostics that touch this range
.filter(x => util.rangesIntersect(x.range, range));
.filter(x => util.rangesIntersectOrTouch(x.range, range));

const scopes = this.getScopesForFile(file);

Expand Down
20 changes: 20 additions & 0 deletions src/bscPlugin/codeActions/CodeActionsProcessor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,24 @@ describe('CodeActionsProcessor', () => {
testGetCodeActions(file, util.createRange(3, 34, 3, 34), [`import "pkg:/source/second.bs"`]);
});
});

it('suggests imports at very start and very end of diagnostic', () => {
program.setFile('source/first.bs', `
namespace alpha
function firstAction()
end function
end namespace
`);
program.setFile('components/MainScene.xml', trim`<component name="MainScene"></component>`);
const file = program.setFile('components/MainScene.bs', `
sub init()
print alpha.firstAction()
end sub
`);

// print |alpha.firstAction()
testGetCodeActions(file, util.createRange(2, 22, 2, 22), [`import "pkg:/source/first.bs"`]);
// print alpha|.firstAction()
testGetCodeActions(file, util.createRange(2, 27, 2, 27), [`import "pkg:/source/first.bs"`]);
});
});
106 changes: 106 additions & 0 deletions src/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,22 @@ describe('util', () => {
});

describe('rangesIntersect', () => {
it('does not match when ranges do not touch (a < b)', () => {
// AA BB
expect(util.rangesIntersectOrTouch(
util.createRange(0, 0, 0, 1),
util.createRange(0, 2, 0, 3)
)).to.be.false;
});

it('does not match when ranges do not touch (a < b)', () => {
// BB AA
expect(util.rangesIntersectOrTouch(
util.createRange(0, 2, 0, 3),
util.createRange(0, 0, 0, 1)
)).to.be.false;
});

it('does not match when ranges touch at right edge', () => {
// AABB
expect(util.rangesIntersect(
Expand Down Expand Up @@ -607,6 +623,96 @@ describe('util', () => {
});
});

describe('rangesIntersectOrTouch', () => {
it('does not match when ranges do not touch (a < b)', () => {
// AA BB
expect(util.rangesIntersectOrTouch(
util.createRange(0, 0, 0, 1),
util.createRange(0, 2, 0, 3)
)).to.be.false;
});

it('does not match when ranges do not touch (a < b)', () => {
// BB AA
expect(util.rangesIntersectOrTouch(
util.createRange(0, 2, 0, 3),
util.createRange(0, 0, 0, 1)
)).to.be.false;
});

it('matches when ranges touch at right edge', () => {
// AABB
expect(util.rangesIntersectOrTouch(
util.createRange(0, 0, 0, 1),
util.createRange(0, 1, 0, 2)
)).to.be.true;
});

it('matches when ranges touch at left edge', () => {
// BBAA
expect(util.rangesIntersectOrTouch(
util.createRange(0, 1, 0, 2),
util.createRange(0, 0, 0, 1)
)).to.be.true;
});

it('matches when range overlaps by single character on the right', () => {
// A BA B
expect(util.rangesIntersectOrTouch(
util.createRange(0, 1, 0, 3),
util.createRange(0, 2, 0, 4)
)).to.be.true;
});

it('matches when range overlaps by single character on the left', () => {
// B AB A
expect(util.rangesIntersectOrTouch(
util.createRange(0, 2, 0, 4),
util.createRange(0, 1, 0, 3)
)).to.be.true;
});

it('matches when A is contained by B at the edges', () => {
// B AA B
expect(util.rangesIntersectOrTouch(
util.createRange(0, 2, 0, 3),
util.createRange(0, 1, 0, 4)
)).to.be.true;
});

it('matches when B is contained by A at the edges', () => {
// A BB A
expect(util.rangesIntersectOrTouch(
util.createRange(0, 1, 0, 4),
util.createRange(0, 2, 0, 3)
)).to.be.true;
});

it('matches when A and B are identical', () => {
// ABBA
expect(util.rangesIntersectOrTouch(
util.createRange(0, 1, 0, 2),
util.createRange(0, 1, 0, 2)
)).to.be.true;
});

it('matches when A spans multiple lines', () => {
// ABBA
expect(util.rangesIntersectOrTouch(
util.createRange(0, 1, 2, 0),
util.createRange(0, 1, 0, 3)
)).to.be.true;
});

it('matches when B spans multiple lines', () => {
// ABBA
expect(util.rangesIntersectOrTouch(
util.createRange(0, 1, 0, 3),
util.createRange(0, 1, 2, 0)
)).to.be.true;
});
});

it('sortByRange', () => {
const front = {
range: util.createRange(1, 1, 1, 2)
Expand Down
32 changes: 31 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,13 @@ export class Util {
}

/**
* Does a touch b in any way?
* Do `a` and `b` overlap by at least one character. This returns false if they are at the edges. Here's some examples:
* ```
* | true | true | true | true | true | false | false | false | false |
* |------|------|------|------|------|-------|-------|-------|-------|
* | aa | aaa | aaa | aaa | a | aa | aa | a | a |
* | bbb | bb | bbb | b | bbb | bb | bb | b | a |
* ```
*/
public rangesIntersect(a: Range, b: Range) {
// Check if `a` is before `b`
Expand All @@ -511,6 +517,30 @@ export class Util {
return true;
}

/**
* Do `a` and `b` overlap by at least one character or touch at the edges
* ```
* | true | true | true | true | true | true | true | false | false |
* |------|------|------|------|------|-------|-------|-------|-------|
* | aa | aaa | aaa | aaa | a | aa | aa | a | a |
* | bbb | bb | bbb | b | bbb | bb | bb | b | a |
* ```
*/
public rangesIntersectOrTouch(a: Range, b: Range) {
// Check if `a` is before `b`
if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character < b.start.character)) {
return false;
}

// Check if `b` is before `a`
if (b.end.line < a.start.line || (b.end.line === a.start.line && b.end.character < a.start.character)) {
return false;
}

// These ranges must intersect
return true;
}

/**
* Test if `position` is in `range`. If the position is at the edges, will return true.
* Adapted from core vscode
Expand Down

0 comments on commit c33d9c0

Please sign in to comment.