mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-17 05:07:37 +08:00
fix(solidity): a call reaches the overload its argument count fits (#2241)
Solidity joins OVERLOADING_LANGUAGES, so retargetSelfOverload moves a call whose argument count the settled overload cannot take to the one sibling that can. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
### Fixes
|
||||
|
||||
- In Solidity, a call to an overloaded function now reaches the overload whose parameter count it fits, as in the other languages with overloading. Before, OpenZeppelin's `_checkRole(role, _msgSender())` inside the one-argument `_checkRole(bytes32 role)` was linked to itself.
|
||||
- In JavaScript and TypeScript, the React conventions for hooks (`use…`) and contexts (`…Context`, `…Provider`) now pick only from the reference's own file. Another file's hook or context is reached only through an import. An optional call like `onSuccess?.(…)` now gets the same scope rules as a plain call. Before, trpc's WebSocket adapter's `createContext?.(…)` option linked to an example app's `createContext`, zod's `schemas.ParseContext` linked to the v3 copy instead of v4's, and bulletproof-react's apps linked `useUser()` to one another's.
|
||||
- In R, a call like `c(1, 2)` is no longer linked to a data variable that happens to share a base function's name, since R skips non-function bindings when it looks up a call. Before, ggplot2's facet tests bound `c <- data_frame(b = 3)`, and every `c(…)` call in those files pointed at that data frame. Functions built by a factory, like ggplot2's `geom_point <- make_constructor(…)`, still resolve.
|
||||
- In Swift, a call to an overloaded method now reaches the overload whose argument labels it spells, with defaulted parameters optional. Before, only the argument count was compared. Alamofire's `self.tableView(tableView, numberOfRowsInSection:)` inside another `tableView` overload linked to itself, and `cancel(optionallyProducingResumeData:)` linked to `cancel(producingResumeData:)`.
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Solidity overloads by parameter count like the other overloading
|
||||
* languages: OpenZeppelin's `_checkRole(role, _msgSender())` inside the
|
||||
* one-argument `_checkRole(bytes32 role)` is the two-argument overload, not
|
||||
* a call to itself.
|
||||
*/
|
||||
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { CodeGraph } from '../src';
|
||||
|
||||
let root = '';
|
||||
let cg: CodeGraph;
|
||||
|
||||
beforeAll(async () => {
|
||||
root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sol-overload-'));
|
||||
const files: Record<string, string> = {
|
||||
'contracts/access/AccessControl.sol': `pragma solidity ^0.8.20;
|
||||
|
||||
abstract contract AccessControl {
|
||||
function _checkRole(bytes32 role) internal view virtual {
|
||||
_checkRole(role, msg.sender);
|
||||
}
|
||||
|
||||
function _checkRole(bytes32 role, address account) internal view virtual {
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
for (const [rel, content] of Object.entries(files)) {
|
||||
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
|
||||
fs.writeFileSync(path.join(root, rel), content);
|
||||
}
|
||||
cg = await CodeGraph.init(root, { index: true });
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
cg?.close();
|
||||
if (root) fs.rmSync(root, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe('Solidity overloads', () => {
|
||||
it('a call reaches the overload its argument count fits', () => {
|
||||
const ids = cg.getNodesInFile('contracts/access/AccessControl.sol').map((n) => n.id);
|
||||
const targets = cg.getOutgoingEdgesFrom(ids).filter((e) => e.kind === 'calls' && e.line === 5).map((e) => cg.getNode(e.target)!.startLine);
|
||||
expect(targets).toEqual([8]);
|
||||
});
|
||||
});
|
||||
@@ -8957,7 +8957,7 @@ function isRFunctionValue(n: Node, context: ResolutionContext): boolean {
|
||||
const VALUE_KINDS: ReadonlySet<string> = new Set(['variable', 'constant', 'field', 'property']);
|
||||
|
||||
/** Languages whose methods overload by arity. */
|
||||
const OVERLOADING_LANGUAGES: ReadonlySet<string> = new Set(['csharp', 'java', 'kotlin', 'swift', 'cpp', 'scala', 'dart', 'vbnet']);
|
||||
const OVERLOADING_LANGUAGES: ReadonlySet<string> = new Set(['csharp', 'java', 'kotlin', 'swift', 'cpp', 'scala', 'dart', 'vbnet', 'solidity']);
|
||||
|
||||
/**
|
||||
* A call a method makes to its own name, with arguments its own parameters
|
||||
|
||||
Reference in New Issue
Block a user