test(r): let the rename verdict helper read <<- and = function definitions

The helper listed only 'name <- function', while the indexer also lists
<<- and = definitions, so a generic defined with = never reached the S3
guard. Add cases that go through the helper with each operator.
This commit is contained in:
Mick Cooney 2026-10-18 13:15:09 +01:00
parent fa909bec19
commit fa219a80ad
2 changed files with 25 additions and 2 deletions

View file

@ -1,7 +1,8 @@
/**
* Run the R rename provider's safety check on real parsed sources and a real knowledge graph.
* `localDefs` are read off the sources the way the indexer would list plain top-level functions
* (`name <- function`), so a function defined in another file is visible to the checks.
* (`name <- function`, `name <<- function` and `name = function`), so a function defined in
* another file is visible to the checks.
*/
import Parser from 'tree-sitter';
import R from '@eagleoutice/tree-sitter-r';
@ -21,7 +22,7 @@ export interface RVerdictInput {
readonly targetFile?: string;
}
const FUNCTION_DEF = /^(`[^`\n]+`|[A-Za-z.][A-Za-z0-9._]*)\s*<-\s*function/gm;
const FUNCTION_DEF = /^(`[^`\n]+`|[A-Za-z.][A-Za-z0-9._]*)\s*(?:<-|<<-|=(?!=))\s*function/gm;
/** The issue the provider reports (`code`, `message`), or null when it accepts the rename. */
export function rIssue(input: RVerdictInput): { code: string; message: string } | null {

View file

@ -48,6 +48,28 @@ describe('R rename: a new name that already exists', () => {
).toBe('name_collision');
});
it.each(['<-', '<<-', '='])(
'lists a function defined with %s, so another file defining the new name is refused',
(op) => {
expect(
rIssue({
files: { 'a.R': HELPER, 'b.R': `assist ${op} function(v) v * 2\n` },
newName: 'assist',
})?.code,
).toBe('name_collision');
},
);
it('sees a generic defined with = when it guards against a new S3 method name', () => {
// `to_json = function(x) x` makes `to_json.foo` an S3 method of an indexed function.
expect(
rIssue({
files: { 'a.R': HELPER, 'b.R': 'to_json = function(x) x\n' },
newName: 'to_json.foo',
})?.code,
).toBe('unsupported_occurrence');
});
it('refuses a <<- to the new name from inside a function', () => {
expect(verdict('install <- function() { assist <<- 3 }\n')).toBe('name_collision');
expect(verdict('install <- function() { 3 ->> assist }\n')).toBe('name_collision');