mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-29 06:32:28 +00:00
feat(r): add conservative semantic rename provider
Plain R functions rename through the scope graph; S3, string-spelled, S4, R6 and NAMESPACE-exported names are refused. Adds fixtures, the rename-provider-r test and its cross-platform shard entries.
This commit is contained in:
parent
56d697256c
commit
3dbf1017ce
45 changed files with 378 additions and 0 deletions
|
|
@ -111,6 +111,20 @@ Not modelled:
|
|||
- `stop()`, `on.exit()`, `tryCatch` handlers and other non-local exits are ordinary calls: no throw edges and no finaliser routing. A `break` / `next` with no enclosing loop falls back to EXIT.
|
||||
- Function join: a CFG is anchored at the `function_definition` token, while the `Function` node starts at the whole assignment. They share a start line for `f <- function`, `f = function` and `f <- \(x)`, but not for `f <-` followed by `function` on the next line; there the CFG is still emitted and its blocks lie inside the `Function` node's span, but the exact start-line join used by taint summaries does not resolve (inert for R today, since reaching definitions have no facts). Anonymous functions have a CFG but no `Function` node.
|
||||
|
||||
## Rename
|
||||
|
||||
`languages/r/rename.ts` gives the `rename` tool a deliberately narrow, fail-closed R provider (fixtures under `test/fixtures/rename-integration/r/`). R binds names dynamically, so only what the scope graph proves is renamed.
|
||||
|
||||
- **Succeeds:** a plain function (`name <- function(...)`) and the calls the graph resolves to it, in one file or across files. A same-named parameter is claimed as a binding and left alone.
|
||||
- **Refused (`unsupported_occurrence`, planning status `unsupported`):**
|
||||
- any target that is not a plain `Function` (S4 classes, R6 classes, members);
|
||||
- a function whose old or new name is spelled as a string literal anywhere in the indexed R sources (`UseMethod("area")`, `do.call("f", ...)`, `match.fun`, `get`, `setGeneric`, ...), because string lookup is not resolved;
|
||||
- a new name `generic.class` whose prefix is an existing function, which would register an S3 method;
|
||||
- a package function under `R/` that `NAMESPACE` does not mark private (`isExported` is not false), because `NAMESPACE` is not an indexed source and its `export()` or `S3method()` entry would go stale.
|
||||
- **Refused by the shared engine (fail-closed, not provider code):** S3 methods and any dotted function name (`area.circle` reads as an owner-qualified member, so `stale_graph`); S4 class names (`unsupported_occurrence`, no exact source-name span); R6 methods (`stale_graph`).
|
||||
- **Invalid names (`invalid_name`):** anything that is not a nonreserved R identifier.
|
||||
- **Not proven:** unqualified calls to a function defined in another file (including the package `R/` layout) fail with `ambiguous_reference`, because R's global-name fallback is not a provable binding. Renaming across files works only where the call is qualified or otherwise resolved.
|
||||
|
||||
## Type annotations
|
||||
|
||||
R has no inline type annotations, so the "Type Annotations" column of the language support table is not ticked for R. The roxygen2 `@param` extraction above is a comment-based fallback, in the same class as the JSDoc, PHPDoc and YARD fallbacks listed in type-resolution-system.md (Ruby's YARD support is likewise not ticked).
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ export const WINDOWS_WEIGHTS_SEC: Readonly<Record<string, number>> = {
|
|||
'test/integration/rename-provider-objective-c.test.ts': 285,
|
||||
'test/integration/rename-provider-php.test.ts': 100,
|
||||
'test/integration/rename-provider-python.test.ts': 375,
|
||||
'test/integration/rename-provider-r.test.ts': 100,
|
||||
'test/integration/rename-provider-ruby.test.ts': 100,
|
||||
'test/integration/rename-provider-rust.test.ts': 75,
|
||||
'test/integration/rename-provider-swift.test.ts': 300,
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ const LBUG_NATIVE = [
|
|||
'test/integration/rename-provider-objective-c.test.ts',
|
||||
'test/integration/rename-provider-php.test.ts',
|
||||
'test/integration/rename-provider-python.test.ts',
|
||||
'test/integration/rename-provider-r.test.ts',
|
||||
'test/integration/rename-provider-ruby.test.ts',
|
||||
'test/integration/rename-provider-rust.test.ts',
|
||||
'test/integration/rename-provider-swift.test.ts',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { rPostParse } from './r/post-parse.js';
|
|||
import { rDefinitionProperties, rResolveMemberOwnerNode } from './r/owner-hooks.js';
|
||||
import { isRNonNamingArgumentCapture } from './r/naming-argument.js';
|
||||
import { createRCfgVisitor } from '../cfg/visitors/r.js';
|
||||
import { rRenameProvider } from './r/rename.js';
|
||||
|
||||
const R_BUILT_INS: ReadonlySet<string> = new Set([
|
||||
// Base R
|
||||
|
|
@ -195,4 +196,5 @@ export const rProvider = defineLanguage({
|
|||
shouldSkipDefinitionCapture: isRNonNamingArgumentCapture,
|
||||
// Control flow only (no def/use harvest): CFG + CDG, REACHING_DEF reports no-facts.
|
||||
cfgVisitor: createRCfgVisitor(),
|
||||
rename: rRenameProvider,
|
||||
});
|
||||
|
|
|
|||
106
gitnexus/src/core/ingestion/languages/r/rename.ts
Normal file
106
gitnexus/src/core/ingestion/languages/r/rename.ts
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import type { NameClaim } from 'gitnexus-shared';
|
||||
import type { RenameIssue, RenameProvider } from '../../rename-provider.js';
|
||||
import {
|
||||
createTreeSitterRenameSource,
|
||||
innermostRenameScope,
|
||||
walkNamedNodes,
|
||||
} from '../rename-tree-sitter.js';
|
||||
|
||||
/**
|
||||
* Conservative semantic rename for R. Plain functions are renamed through the
|
||||
* scope-resolution graph. R binds names dynamically (S3/S4/R6 dispatch, strings,
|
||||
* NAMESPACE), so every declaration or name that the graph cannot prove is refused.
|
||||
*/
|
||||
const RESERVED = new Set(
|
||||
'if else repeat while function for next break TRUE FALSE NULL Inf NaN NA NA_integer_ NA_real_ NA_character_ NA_complex_ in'.split(
|
||||
' ',
|
||||
),
|
||||
);
|
||||
|
||||
const unsupported = (message: string): RenameIssue => ({
|
||||
code: 'unsupported_occurrence',
|
||||
status: 'unsupported',
|
||||
message,
|
||||
});
|
||||
|
||||
const parseNames = createTreeSitterRenameSource({
|
||||
isName: (node) => node.type === 'identifier',
|
||||
skip: (node) => node.type === 'comment',
|
||||
role: (node) =>
|
||||
node.parent?.type === 'parameter' && node.parent.childForFieldName('name')?.id === node.id
|
||||
? 'binding'
|
||||
: 'name',
|
||||
});
|
||||
|
||||
export const rRenameProvider: RenameProvider = {
|
||||
validateName(name) {
|
||||
if (!/^(?:[A-Za-z]|\.(?![0-9]))[A-Za-z0-9._]*$/.test(name) || RESERVED.has(name))
|
||||
return { code: 'invalid_name', message: 'Choose a valid nonreserved R identifier.' };
|
||||
},
|
||||
async parseSource(input) {
|
||||
const source = await parseNames(input);
|
||||
// Parameters shadow same-named functions: claim them per scope so the engine
|
||||
// leaves an unrelated parameter alone.
|
||||
const claims = new Map<string, NameClaim[]>();
|
||||
for (const occurrence of source.occurrences) {
|
||||
if (occurrence.role !== 'binding' || !occurrence.node) continue;
|
||||
const scope = innermostRenameScope(source.parsed, occurrence.node);
|
||||
if (!scope) continue;
|
||||
claims.set(scope, [
|
||||
...(claims.get(scope) ?? []),
|
||||
{
|
||||
name: occurrence.name,
|
||||
range: occurrence.range,
|
||||
kind: 'binding',
|
||||
hoisted: true,
|
||||
purpose: 'value',
|
||||
},
|
||||
]);
|
||||
}
|
||||
return {
|
||||
...source,
|
||||
parsed: {
|
||||
...source.parsed,
|
||||
scopes: source.parsed.scopes.map((scope) => ({
|
||||
...scope,
|
||||
nameClaims: [...(scope.nameClaims ?? []), ...(claims.get(scope.id) ?? [])],
|
||||
})),
|
||||
},
|
||||
};
|
||||
},
|
||||
checkSafety({ target, newName, files, graph }) {
|
||||
const name = target.qualifiedName ?? '';
|
||||
if (target.type !== 'Function')
|
||||
return unsupported('Only plain R functions can be renamed; classes and members are refused.');
|
||||
const defined = new Set(
|
||||
[...files.values()].flatMap((source) => source.parsed.localDefs.map((d) => d.qualifiedName)),
|
||||
);
|
||||
if (newName.includes('.') && defined.has(newName.slice(0, newName.indexOf('.'))))
|
||||
return unsupported('The new name would register an S3 method of an existing function.');
|
||||
for (const source of files.values()) {
|
||||
if (!source.tree) continue;
|
||||
for (const node of walkNamedNodes(source.tree.rootNode)) {
|
||||
if (node.type === 'string_content' && (node.text === name || node.text === newName))
|
||||
return unsupported(
|
||||
'A string literal spells this name; S3, S4, R6 and dynamic lookup resolve it by string.',
|
||||
);
|
||||
}
|
||||
}
|
||||
// NAMESPACE is not an indexed source. A package function that the NAMESPACE
|
||||
// exports (the graph keeps isExported unless it is proven private) is refused.
|
||||
const file = target.filePath;
|
||||
let exported = false;
|
||||
graph.forEachNode((node) => {
|
||||
if (
|
||||
node.properties.filePath === file &&
|
||||
node.properties.name === name &&
|
||||
node.properties.isExported !== false
|
||||
)
|
||||
exported = true;
|
||||
});
|
||||
if (exported && /(^|\/)R\//.test(file))
|
||||
return unsupported(
|
||||
'A package function may have a NAMESPACE export entry that is not renamed.',
|
||||
);
|
||||
},
|
||||
};
|
||||
10
gitnexus/test/fixtures/rename-integration/r/function-call-chain/after/chain.R
vendored
Normal file
10
gitnexus/test/fixtures/rename-integration/r/function-call-chain/after/chain.R
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
assist <- function(v) v + 1
|
||||
|
||||
step <- function(v) {
|
||||
assist(assist(v))
|
||||
}
|
||||
|
||||
# helper is described here
|
||||
main <- function() {
|
||||
step(1)
|
||||
}
|
||||
10
gitnexus/test/fixtures/rename-integration/r/function-call-chain/before/chain.R
vendored
Normal file
10
gitnexus/test/fixtures/rename-integration/r/function-call-chain/before/chain.R
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
helper <- function(v) v + 1
|
||||
|
||||
step <- function(v) {
|
||||
helper(helper(v))
|
||||
}
|
||||
|
||||
# helper is described here
|
||||
main <- function() {
|
||||
step(1)
|
||||
}
|
||||
15
gitnexus/test/fixtures/rename-integration/r/function-call-chain/case.json
vendored
Normal file
15
gitnexus/test/fixtures/rename-integration/r/function-call-chain/case.json
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Rename a plain function called twice in one expression; a comment mentioning the name is untouched.",
|
||||
"categories": ["call-graph", "same-file", "comments"],
|
||||
"target": { "name": "helper", "kind": "Function", "file": "chain.R", "startLine": 0 },
|
||||
"newName": "assist",
|
||||
"expect": { "status": "success", "edits": 3 },
|
||||
"edges": [
|
||||
{
|
||||
"type": "CALLS",
|
||||
"from": { "name": "step", "kind": "Function", "file": "chain.R", "startLine": 2 },
|
||||
"to": { "name": "helper", "kind": "Function", "file": "chain.R", "startLine": 0 }
|
||||
}
|
||||
]
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/after/apply.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/after/apply.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
apply_twice <- function(compute, v) {
|
||||
compute(compute(v))
|
||||
}
|
||||
7
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/after/lib.R
vendored
Normal file
7
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/after/lib.R
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
calculate <- function(x) {
|
||||
x * 2
|
||||
}
|
||||
|
||||
run <- function(y) {
|
||||
calculate(y) + 1
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/before/apply.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/before/apply.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
apply_twice <- function(compute, v) {
|
||||
compute(compute(v))
|
||||
}
|
||||
7
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/before/lib.R
vendored
Normal file
7
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/before/lib.R
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
compute <- function(x) {
|
||||
x * 2
|
||||
}
|
||||
|
||||
run <- function(y) {
|
||||
compute(y) + 1
|
||||
}
|
||||
15
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/case.json
vendored
Normal file
15
gitnexus/test/fixtures/rename-integration/r/function-unrelated-parameter/case.json
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Rename a plain function called in its own file while a same-named parameter in a second file is left alone.",
|
||||
"categories": ["call-graph", "cross-file", "parameter-shadowing"],
|
||||
"target": { "name": "compute", "kind": "Function", "file": "lib.R", "startLine": 0 },
|
||||
"newName": "calculate",
|
||||
"expect": { "status": "success", "edits": 2 },
|
||||
"edges": [
|
||||
{
|
||||
"type": "CALLS",
|
||||
"from": { "name": "run", "kind": "Function", "file": "lib.R", "startLine": 4 },
|
||||
"to": { "name": "compute", "kind": "Function", "file": "lib.R", "startLine": 0 }
|
||||
}
|
||||
]
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-invalid-start/after/lib.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-invalid-start/after/lib.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
tick <- function(x) x + 1
|
||||
|
||||
run <- function() tick(1)
|
||||
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-invalid-start/before/lib.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-invalid-start/before/lib.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
tick <- function(x) x + 1
|
||||
|
||||
run <- function() tick(1)
|
||||
9
gitnexus/test/fixtures/rename-integration/r/invalid-name-invalid-start/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/invalid-name-invalid-start/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse a name starting with a digit as the new function name.",
|
||||
"categories": ["identifier-rules", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "tick", "kind": "Function", "file": "lib.R", "startLine": 0 },
|
||||
"newName": "2fast",
|
||||
"expect": { "status": "error", "code": "invalid_name", "planningStatus": "blocked" },
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-reserved-word/after/lib.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-reserved-word/after/lib.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
tick <- function(x) x + 1
|
||||
|
||||
run <- function() tick(1)
|
||||
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-reserved-word/before/lib.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/invalid-name-reserved-word/before/lib.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
tick <- function(x) x + 1
|
||||
|
||||
run <- function() tick(1)
|
||||
9
gitnexus/test/fixtures/rename-integration/r/invalid-name-reserved-word/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/invalid-name-reserved-word/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse a reserved word as the new function name.",
|
||||
"categories": ["identifier-rules", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "tick", "kind": "Function", "file": "lib.R", "startLine": 0 },
|
||||
"newName": "repeat",
|
||||
"expect": { "status": "error", "code": "invalid_name", "planningStatus": "blocked" },
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/namespace-export/after/DESCRIPTION
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/namespace-export/after/DESCRIPTION
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Package: pk
|
||||
Version: 0.1.0
|
||||
Title: Fixture
|
||||
1
gitnexus/test/fixtures/rename-integration/r/namespace-export/after/NAMESPACE
vendored
Normal file
1
gitnexus/test/fixtures/rename-integration/r/namespace-export/after/NAMESPACE
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export(compute)
|
||||
5
gitnexus/test/fixtures/rename-integration/r/namespace-export/after/R/lib.R
vendored
Normal file
5
gitnexus/test/fixtures/rename-integration/r/namespace-export/after/R/lib.R
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
compute <- function(x) {
|
||||
x * 2
|
||||
}
|
||||
|
||||
use_it <- function() compute(2)
|
||||
3
gitnexus/test/fixtures/rename-integration/r/namespace-export/before/DESCRIPTION
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/namespace-export/before/DESCRIPTION
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Package: pk
|
||||
Version: 0.1.0
|
||||
Title: Fixture
|
||||
1
gitnexus/test/fixtures/rename-integration/r/namespace-export/before/NAMESPACE
vendored
Normal file
1
gitnexus/test/fixtures/rename-integration/r/namespace-export/before/NAMESPACE
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export(compute)
|
||||
5
gitnexus/test/fixtures/rename-integration/r/namespace-export/before/R/lib.R
vendored
Normal file
5
gitnexus/test/fixtures/rename-integration/r/namespace-export/before/R/lib.R
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
compute <- function(x) {
|
||||
x * 2
|
||||
}
|
||||
|
||||
use_it <- function() compute(2)
|
||||
9
gitnexus/test/fixtures/rename-integration/r/namespace-export/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/namespace-export/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse a package function that NAMESPACE exports, because the export entry would go stale.",
|
||||
"categories": ["namespace", "package-export", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "compute", "kind": "Function", "file": "R/lib.R", "startLine": 0 },
|
||||
"newName": "calculate",
|
||||
"expect": { "status": "error", "code": "unsupported_occurrence", "planningStatus": "unsupported" },
|
||||
"edges": []
|
||||
}
|
||||
11
gitnexus/test/fixtures/rename-integration/r/r6-class/after/account.R
vendored
Normal file
11
gitnexus/test/fixtures/rename-integration/r/r6-class/after/account.R
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Account <- R6::R6Class("Account",
|
||||
public = list(
|
||||
balance = 0,
|
||||
deposit = function(n) {
|
||||
self$balance <- self$balance + n
|
||||
invisible(self)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
acc <- Account$new()
|
||||
11
gitnexus/test/fixtures/rename-integration/r/r6-class/before/account.R
vendored
Normal file
11
gitnexus/test/fixtures/rename-integration/r/r6-class/before/account.R
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Account <- R6::R6Class("Account",
|
||||
public = list(
|
||||
balance = 0,
|
||||
deposit = function(n) {
|
||||
self$balance <- self$balance + n
|
||||
invisible(self)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
acc <- Account$new()
|
||||
9
gitnexus/test/fixtures/rename-integration/r/r6-class/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/r6-class/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse an R6 class whose members and constructor are reached through $new and self.",
|
||||
"categories": ["r6", "class", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "Account", "kind": "Class", "file": "account.R", "startLine": 0 },
|
||||
"newName": "Wallet",
|
||||
"expect": { "status": "error", "code": "unsupported_occurrence", "planningStatus": "unsupported" },
|
||||
"edges": []
|
||||
}
|
||||
5
gitnexus/test/fixtures/rename-integration/r/s3-generic/after/shapes.R
vendored
Normal file
5
gitnexus/test/fixtures/rename-integration/r/s3-generic/after/shapes.R
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
area <- function(x) UseMethod("area")
|
||||
|
||||
area.circle <- function(x) 3.14 * x$r^2
|
||||
|
||||
total <- function(s) area(s)
|
||||
5
gitnexus/test/fixtures/rename-integration/r/s3-generic/before/shapes.R
vendored
Normal file
5
gitnexus/test/fixtures/rename-integration/r/s3-generic/before/shapes.R
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
area <- function(x) UseMethod("area")
|
||||
|
||||
area.circle <- function(x) 3.14 * x$r^2
|
||||
|
||||
total <- function(s) area(s)
|
||||
9
gitnexus/test/fixtures/rename-integration/r/s3-generic/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/s3-generic/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse an S3 generic whose UseMethod string and area.circle method dispatch by spelling.",
|
||||
"categories": ["s3", "string-dispatch", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "area", "kind": "Function", "file": "shapes.R", "startLine": 0 },
|
||||
"newName": "surface",
|
||||
"expect": { "status": "error", "code": "unsupported_occurrence", "planningStatus": "unsupported" },
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/s3-method/after/shapes.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/s3-method/after/shapes.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
area <- function(x) UseMethod("area")
|
||||
|
||||
area.circle <- function(x) 3.14 * x$r^2
|
||||
3
gitnexus/test/fixtures/rename-integration/r/s3-method/before/shapes.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/s3-method/before/shapes.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
area <- function(x) UseMethod("area")
|
||||
|
||||
area.circle <- function(x) 3.14 * x$r^2
|
||||
23
gitnexus/test/fixtures/rename-integration/r/s3-method/case.json
vendored
Normal file
23
gitnexus/test/fixtures/rename-integration/r/s3-method/case.json
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse an S3 method: its dotted name is read as an owner-qualified member, so the graph identity is not a unique source declaration.",
|
||||
"categories": [
|
||||
"s3",
|
||||
"dotted-name",
|
||||
"negative",
|
||||
"unchanged-on-error"
|
||||
],
|
||||
"target": {
|
||||
"name": "area.circle",
|
||||
"kind": "Function",
|
||||
"file": "shapes.R",
|
||||
"startLine": 2
|
||||
},
|
||||
"newName": "round_area",
|
||||
"expect": {
|
||||
"status": "error",
|
||||
"code": "stale_graph",
|
||||
"planningStatus": "blocked"
|
||||
},
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/s3-new-method-name/after/shapes.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/s3-new-method-name/after/shapes.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
area <- function(x) 1
|
||||
|
||||
circle_area <- function(x) 3.14 * x$r^2
|
||||
3
gitnexus/test/fixtures/rename-integration/r/s3-new-method-name/before/shapes.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/s3-new-method-name/before/shapes.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
area <- function(x) 1
|
||||
|
||||
circle_area <- function(x) 3.14 * x$r^2
|
||||
9
gitnexus/test/fixtures/rename-integration/r/s3-new-method-name/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/s3-new-method-name/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse a new dotted name whose prefix is an existing function, which would silently register an S3 method of it.",
|
||||
"categories": ["s3", "name-collision", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "circle_area", "kind": "Function", "file": "shapes.R", "startLine": 2 },
|
||||
"newName": "area.circle",
|
||||
"expect": { "status": "error", "code": "unsupported_occurrence", "planningStatus": "unsupported" },
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/s4-class/after/person.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/s4-class/after/person.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
setClass("Person", representation(name = "character"))
|
||||
|
||||
make <- function() new("Person", name = "a")
|
||||
3
gitnexus/test/fixtures/rename-integration/r/s4-class/before/person.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/s4-class/before/person.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
setClass("Person", representation(name = "character"))
|
||||
|
||||
make <- function() new("Person", name = "a")
|
||||
9
gitnexus/test/fixtures/rename-integration/r/s4-class/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/s4-class/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse an S4 class whose name is spelled only in string literals.",
|
||||
"categories": ["s4", "class", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "Person", "kind": "Class", "file": "person.R", "startLine": 0 },
|
||||
"newName": "Human",
|
||||
"expect": { "status": "error", "code": "unsupported_occurrence", "planningStatus": "unsupported" },
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/fixtures/rename-integration/r/string-lookup/after/dyn.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/string-lookup/after/dyn.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
worker <- function(x) x + 1
|
||||
|
||||
run <- function() do.call("worker", list(1))
|
||||
3
gitnexus/test/fixtures/rename-integration/r/string-lookup/before/dyn.R
vendored
Normal file
3
gitnexus/test/fixtures/rename-integration/r/string-lookup/before/dyn.R
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
worker <- function(x) x + 1
|
||||
|
||||
run <- function() do.call("worker", list(1))
|
||||
9
gitnexus/test/fixtures/rename-integration/r/string-lookup/case.json
vendored
Normal file
9
gitnexus/test/fixtures/rename-integration/r/string-lookup/case.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"language": "r",
|
||||
"description": "Refuse a function that a string literal names for do.call dynamic lookup.",
|
||||
"categories": ["string-dispatch", "negative", "unchanged-on-error"],
|
||||
"target": { "name": "worker", "kind": "Function", "file": "dyn.R", "startLine": 0 },
|
||||
"newName": "job",
|
||||
"expect": { "status": "error", "code": "unsupported_occurrence", "planningStatus": "unsupported" },
|
||||
"edges": []
|
||||
}
|
||||
3
gitnexus/test/integration/rename-provider-r.test.ts
Normal file
3
gitnexus/test/integration/rename-provider-r.test.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { defineRenameFixtureTests } from '../helpers/rename-integration-cases.js';
|
||||
|
||||
defineRenameFixtureTests('r');
|
||||
Loading…
Add table
Reference in a new issue