* Check if reference is to a built-in or external symbol
(ref: UnresolvedRef)
| 1972 | * Check if reference is to a built-in or external symbol |
| 1973 | */ |
| 1974 | private isBuiltInOrExternal(ref: UnresolvedRef): boolean { |
| 1975 | const name = ref.referenceName; |
| 1976 | const isJsTs = ref.language === 'typescript' || ref.language === 'javascript' |
| 1977 | || ref.language === 'tsx' || ref.language === 'jsx' || ref.language === 'arkts'; |
| 1978 | |
| 1979 | // JavaScript/TypeScript built-ins |
| 1980 | if (isJsTs && JS_BUILT_INS.has(name)) { |
| 1981 | return true; |
| 1982 | } |
| 1983 | |
| 1984 | // ArkTS resource-reference intrinsics — `$r('app.string.x')` / |
| 1985 | // `$rawfile('x.png')` are framework-provided and appear dozens of times |
| 1986 | // per UI file; without this they can resolve to a stray same-named |
| 1987 | // symbol (e.g. a checked-in hvigor wrapper's `$r`). |
| 1988 | if (ref.language === 'arkts' && (name === '$r' || name === '$rawfile')) { |
| 1989 | return true; |
| 1990 | } |
| 1991 | |
| 1992 | // Common JS/TS library calls (console.log, Math.floor, JSON.parse) |
| 1993 | if (isJsTs && (name.startsWith('console.') || name.startsWith('Math.') || name.startsWith('JSON.'))) { |
| 1994 | return true; |
| 1995 | } |
| 1996 | |
| 1997 | // React hooks from React itself |
| 1998 | if (isJsTs && REACT_HOOKS.has(name)) { |
| 1999 | return true; |
| 2000 | } |
| 2001 | |
| 2002 | // Python built-ins (bare calls only — dotted calls like console.print are method calls) |
| 2003 | if (ref.language === 'python' && PYTHON_BUILT_INS.has(name)) { |
| 2004 | return true; |
| 2005 | } |
| 2006 | |
| 2007 | // Python built-in method calls (e.g., list.extend, dict.update) |
| 2008 | if (ref.language === 'python') { |
| 2009 | const dotIdx = name.indexOf('.'); |
| 2010 | if (dotIdx > 0) { |
| 2011 | const receiver = name.substring(0, dotIdx); |
| 2012 | const method = name.substring(dotIdx + 1); |
| 2013 | // Filter calls on built-in types (list.append, dict.update, etc.) |
| 2014 | if (PYTHON_BUILT_IN_TYPES.has(receiver)) { |
| 2015 | return true; |
| 2016 | } |
| 2017 | // Filter built-in methods on non-class receivers |
| 2018 | // (e.g., items.append where items is a local list variable) |
| 2019 | // But allow if the capitalized receiver matches a known codebase class |
| 2020 | if (PYTHON_BUILT_IN_METHODS.has(method)) { |
| 2021 | const capitalized = receiver.charAt(0).toUpperCase() + receiver.slice(1); |
| 2022 | if (!this.knownNames?.has(capitalized)) { |
| 2023 | return true; |
| 2024 | } |
| 2025 | } |
| 2026 | } |
| 2027 | // A bare name colliding with a builtin method (index, get, update, count…) |
| 2028 | // is only a builtin when NOTHING in the codebase declares it. A declared |
| 2029 | // symbol with that exact name — e.g. a Flask/FastAPI view `def index()` or |
| 2030 | // `def get()` — is a real reference target. Mirrors the knownNames guard on |
| 2031 | // the dotted branch above; without it, every handler named after a builtin |
no test coverage detected