diff --git a/README.md b/README.md index c8609da17..a67eb4c99 100644 --- a/README.md +++ b/README.md @@ -708,7 +708,7 @@ GitNexus builds a complete knowledge graph of your codebase through a multi-phas **Imports** — cross-file import resolution · **Named Bindings** — `import { X as Y }` / re-export tracking · **Exports** — public/exported symbol detection · **Heritage** — class inheritance, interfaces, mixins · **Type Annotations** — explicit type extraction for receiver resolution · **Constructor Inference** — infer receiver type from constructor calls (`self`/`this` resolution included for all languages) · **Config** — language toolchain config parsing (tsconfig, go.mod, etc.) · **Frameworks** — AST-based framework pattern detection · **Entry Points** — entry point scoring heuristics -**R (experimental)** — `.r` / `.R` files, parsed with `@eagleoutice/tree-sitter-r`. Extracts functions (S3 methods appear as dotted-name functions such as `print.foo`), S4 classes (`setClass`, `setGeneric`, `setMethod`, slots), R6 classes with their methods and fields, R5 (`setRefClass`) methods, and roxygen2 `@param` types. The scope-resolution pipeline resolves `library()` / `require()` / `source()` imports to local packages and files, binds NAMESPACE `importFrom()` names to definitions in local packages, resolves `obj$method()` calls (receiver type inferred from `Type$new()`), follows calls inside native pipe (`|>`) chains, and links R6 `inherit=` / S4 `contains=` heritage. Export status is read from each local package's NAMESPACE (a `DESCRIPTION` marks the package): `export()`, `exportClasses()`, `exportMethods()`, `S3method()` and `exportPattern()` (multi-line directives, R string escapes and POSIX character classes handled) decide which symbols keep `isExported`; the language-level export check treats every symbol as public, and the NAMESPACE pass then marks the rest of the `R/` symbols of a NAMESPACE-bearing package non-exported (symbols outside `R/`, such as `tests/`, `vignettes/` and `inst/`, are not package members and stay public; files in `R/` subdirectories are treated as `R/` files although R itself does not load them). Packages without a NAMESPACE stay fully public and a nested package without one does not inherit its enclosing package's; roxygen2 `@export` tags are not consulted. An index of an R repository built before these rules needs a re-analyse to pick them up: export status outside `R/`, `library()` of a root-level package (now linked), and `foo::f()` where `foo` is only the directory name of a package with a different `Package:` name (now no name-based edge). Known limits: a bare call to a function in another file of the same package binds through a workspace-wide unique-name fallback at confidence 0.5 (`global-name-fallback`), not package-namespace lookup, and an ambiguous name yields no edge; dotted (S3-style) names are never import-resolved and bind by qualified-name lookup at 0.35; a qualified call `pkg::name()` is decided by its qualifier: when `pkg` is a package of the repository and defines `name` exactly once, the call binds to that definition at confidence 0.85 (`import-resolved`); when `pkg` is certainly not a repository package (package discovery completed and found no such package, including a repository with no `DESCRIPTION` at all), the call produces no edge; when `pkg` defines `name` more than once the call produces no edge; and when discovery may have missed a package (its depth and directory limits were reached and an unscanned subtree may hold an undiscovered package) the call keeps the name-based behaviour. Remaining gaps: a repository package that does not itself define `name` (for example a re-export) keeps the name-based behaviour; `pkg::name` used as a value rather than called (`lapply(x, pkg::name)`) is not resolved; a `::` to a name the package does not export still binds to its definition; and packages are discovered only to a bounded depth and directory count, so a package outside those limits is treated like an unknown one, while directories named exactly `renv`, `packrat`, `revdep` or `.Rcheck` (installed libraries and check output) are never searched, so a package found only there is not a repository package; `import()`, `importClassesFrom()` and `importMethodsFrom()` are not read; `exportPattern()` character classes use ASCII semantics; S4 `contains=` links only to classes defined in the repository or the `VIRTUAL` marker, so basic-type bases add no edge; imports of external (CRAN) packages produce no edges; an edit to NAMESPACE alone is not re-resolved by an incremental re-index, so run a full analyze after changing it; no framework or entry-point detection. +**R (experimental)** — `.r` / `.R` files, parsed with `@eagleoutice/tree-sitter-r`. Extracts functions (S3 methods appear as dotted-name functions such as `print.foo`), S4 classes (`setClass`, `setGeneric`, `setMethod`, slots), R6 classes with their methods and fields, R5 (`setRefClass`) methods, and roxygen2 `@param` types. The scope-resolution pipeline resolves `library()` / `require()` / `source()` imports to local packages and files, binds NAMESPACE `importFrom()` names to definitions in local packages, resolves `obj$method()` calls (receiver type inferred from `Type$new()`), follows calls inside native pipe (`|>`) chains, and links R6 `inherit=` / S4 `contains=` heritage. Export status is read from each local package's NAMESPACE (a `DESCRIPTION` marks the package): `export()`, `exportClasses()`, `exportMethods()`, `S3method()` and `exportPattern()` (multi-line directives, R string escapes and POSIX character classes handled) decide which symbols keep `isExported`; the language-level export check treats every symbol as public, and the NAMESPACE pass then marks the rest of the `R/` symbols of a NAMESPACE-bearing package non-exported (symbols outside `R/`, such as `tests/`, `vignettes/` and `inst/`, are not package members and stay public; files in `R/` subdirectories are treated as `R/` files although R itself does not load them). Packages without a NAMESPACE stay fully public and a nested package without one does not inherit its enclosing package's; roxygen2 `@export` tags are not consulted. An index of an R repository built before these rules needs a re-analyse to pick them up: export status (outside `R/`, and inside `R/` for a nested package without a NAMESPACE), `library()` of a root-level package (now linked), and `foo::f()` where `foo` is only the directory name of a package with a different `Package:` name (the call loses its name-based edge when package discovery was not truncated, or binds to a definition that duplicate definitions had previously dropped it for). Known limits: a bare call to a function in another file of the same package binds through a workspace-wide unique-name fallback at confidence 0.5 (`global-name-fallback`), not package-namespace lookup, and an ambiguous name yields no edge; dotted (S3-style) names are never import-resolved and bind by qualified-name lookup at 0.35; a qualified call `pkg::name()` is decided by its qualifier: when `pkg` is a package of the repository and defines `name` exactly once, the call binds to that definition at confidence 0.85 (`import-resolved`); when `pkg` is certainly not a repository package (package discovery completed and found no such package, including a repository with no `DESCRIPTION` at all), the call produces no edge; when `pkg` defines `name` more than once the call produces no edge; and when discovery may have missed a package (its depth and directory limits were reached and an unscanned subtree may hold an undiscovered package) the call keeps the name-based behaviour. Remaining gaps: a repository package that does not itself define `name` (for example a re-export) keeps the name-based behaviour; `pkg::name` used as a value rather than called (`lapply(x, pkg::name)`) is not resolved; a `::` to a name the package does not export still binds to its definition; and packages are discovered only to a bounded depth and directory count, so a package outside those limits is treated like an unknown one, while directories named exactly `renv`, `packrat`, `revdep` or `.Rcheck` (installed libraries and check output) are never searched, so a package found only there is not a repository package; `import()`, `importClassesFrom()` and `importMethodsFrom()` are not read; `exportPattern()` character classes use ASCII semantics; S4 `contains=` links only to classes defined in the repository or the `VIRTUAL` marker, so basic-type bases add no edge; imports of external (CRAN) packages produce no edges; an edit to NAMESPACE alone is not re-resolved by an incremental re-index, so run a full analyze after changing it; no framework or entry-point detection. **Control flow (CFG, opt-in `--pdg`)** — per-function control-flow graphs (`BasicBlock` nodes + `CFG` edges) feeding the PDG/taint substrate, currently **TypeScript & JavaScript** (#2081 M1); other languages planned. Off by default. diff --git a/gitnexus/README.md b/gitnexus/README.md index 61d784962..955d04f12 100644 --- a/gitnexus/README.md +++ b/gitnexus/README.md @@ -484,7 +484,7 @@ TypeScript, JavaScript, Python, Java, C, C++, C#, Go, Rust, PHP, Kotlin, Swift, **Imports** — cross-file import resolution · **Named Bindings** — `import { X as Y }` / re-export tracking · **Exports** — public/exported symbol detection · **Heritage** — class inheritance, interfaces, mixins · **Type Annotations** — explicit type extraction for receiver resolution · **Constructor Inference** — infer receiver type from constructor calls (`self`/`this` resolution included for all languages) · **Config** — language toolchain config parsing (tsconfig, go.mod, etc.) · **Frameworks** — AST-based framework pattern detection · **Entry Points** — entry point scoring heuristics -**R (experimental)** — `.r` / `.R` files, parsed with `@eagleoutice/tree-sitter-r`. Extracts functions (S3 methods appear as dotted-name functions such as `print.foo`), S4 classes (`setClass`, `setGeneric`, `setMethod`, slots), R6 classes with their methods and fields, R5 (`setRefClass`) methods, and roxygen2 `@param` types. The scope-resolution pipeline resolves `library()` / `require()` / `source()` imports to local packages and files, binds NAMESPACE `importFrom()` names to definitions in local packages, resolves `obj$method()` calls (receiver type inferred from `Type$new()`), follows calls inside native pipe (`|>`) chains, and links R6 `inherit=` / S4 `contains=` heritage. Export status is read from each local package's NAMESPACE (a `DESCRIPTION` marks the package): `export()`, `exportClasses()`, `exportMethods()`, `S3method()` and `exportPattern()` (multi-line directives, R string escapes and POSIX character classes handled) decide which symbols keep `isExported`; the language-level export check treats every symbol as public, and the NAMESPACE pass then marks the rest of the `R/` symbols of a NAMESPACE-bearing package non-exported (symbols outside `R/`, such as `tests/`, `vignettes/` and `inst/`, are not package members and stay public; files in `R/` subdirectories are treated as `R/` files although R itself does not load them). Packages without a NAMESPACE stay fully public and a nested package without one does not inherit its enclosing package's; roxygen2 `@export` tags are not consulted. An index of an R repository built before these rules needs a re-analyse to pick them up: export status outside `R/`, `library()` of a root-level package (now linked), and `foo::f()` where `foo` is only the directory name of a package with a different `Package:` name (now no name-based edge). Known limits: a bare call to a function in another file of the same package binds through a workspace-wide unique-name fallback at confidence 0.5 (`global-name-fallback`), not package-namespace lookup, and an ambiguous name yields no edge; dotted (S3-style) names are never import-resolved and bind by qualified-name lookup at 0.35; a qualified call `pkg::name()` is decided by its qualifier: when `pkg` is a package of the repository and defines `name` exactly once, the call binds to that definition at confidence 0.85 (`import-resolved`); when `pkg` is certainly not a repository package (package discovery completed and found no such package, including a repository with no `DESCRIPTION` at all), the call produces no edge; when `pkg` defines `name` more than once the call produces no edge; and when discovery may have missed a package (its depth and directory limits were reached and an unscanned subtree may hold an undiscovered package) the call keeps the name-based behaviour. Remaining gaps: a repository package that does not itself define `name` (for example a re-export) keeps the name-based behaviour; `pkg::name` used as a value rather than called (`lapply(x, pkg::name)`) is not resolved; a `::` to a name the package does not export still binds to its definition; and packages are discovered only to a bounded depth and directory count, so a package outside those limits is treated like an unknown one, while directories named exactly `renv`, `packrat`, `revdep` or `.Rcheck` (installed libraries and check output) are never searched, so a package found only there is not a repository package; `import()`, `importClassesFrom()` and `importMethodsFrom()` are not read; `exportPattern()` character classes use ASCII semantics; S4 `contains=` links only to classes defined in the repository or the `VIRTUAL` marker, so basic-type bases add no edge; imports of external (CRAN) packages produce no edges; an edit to NAMESPACE alone is not re-resolved by an incremental re-index, so run a full analyze after changing it; no framework or entry-point detection. +**R (experimental)** — `.r` / `.R` files, parsed with `@eagleoutice/tree-sitter-r`. Extracts functions (S3 methods appear as dotted-name functions such as `print.foo`), S4 classes (`setClass`, `setGeneric`, `setMethod`, slots), R6 classes with their methods and fields, R5 (`setRefClass`) methods, and roxygen2 `@param` types. The scope-resolution pipeline resolves `library()` / `require()` / `source()` imports to local packages and files, binds NAMESPACE `importFrom()` names to definitions in local packages, resolves `obj$method()` calls (receiver type inferred from `Type$new()`), follows calls inside native pipe (`|>`) chains, and links R6 `inherit=` / S4 `contains=` heritage. Export status is read from each local package's NAMESPACE (a `DESCRIPTION` marks the package): `export()`, `exportClasses()`, `exportMethods()`, `S3method()` and `exportPattern()` (multi-line directives, R string escapes and POSIX character classes handled) decide which symbols keep `isExported`; the language-level export check treats every symbol as public, and the NAMESPACE pass then marks the rest of the `R/` symbols of a NAMESPACE-bearing package non-exported (symbols outside `R/`, such as `tests/`, `vignettes/` and `inst/`, are not package members and stay public; files in `R/` subdirectories are treated as `R/` files although R itself does not load them). Packages without a NAMESPACE stay fully public and a nested package without one does not inherit its enclosing package's; roxygen2 `@export` tags are not consulted. An index of an R repository built before these rules needs a re-analyse to pick them up: export status (outside `R/`, and inside `R/` for a nested package without a NAMESPACE), `library()` of a root-level package (now linked), and `foo::f()` where `foo` is only the directory name of a package with a different `Package:` name (the call loses its name-based edge when package discovery was not truncated, or binds to a definition that duplicate definitions had previously dropped it for). Known limits: a bare call to a function in another file of the same package binds through a workspace-wide unique-name fallback at confidence 0.5 (`global-name-fallback`), not package-namespace lookup, and an ambiguous name yields no edge; dotted (S3-style) names are never import-resolved and bind by qualified-name lookup at 0.35; a qualified call `pkg::name()` is decided by its qualifier: when `pkg` is a package of the repository and defines `name` exactly once, the call binds to that definition at confidence 0.85 (`import-resolved`); when `pkg` is certainly not a repository package (package discovery completed and found no such package, including a repository with no `DESCRIPTION` at all), the call produces no edge; when `pkg` defines `name` more than once the call produces no edge; and when discovery may have missed a package (its depth and directory limits were reached and an unscanned subtree may hold an undiscovered package) the call keeps the name-based behaviour. Remaining gaps: a repository package that does not itself define `name` (for example a re-export) keeps the name-based behaviour; `pkg::name` used as a value rather than called (`lapply(x, pkg::name)`) is not resolved; a `::` to a name the package does not export still binds to its definition; and packages are discovered only to a bounded depth and directory count, so a package outside those limits is treated like an unknown one, while directories named exactly `renv`, `packrat`, `revdep` or `.Rcheck` (installed libraries and check output) are never searched, so a package found only there is not a repository package; `import()`, `importClassesFrom()` and `importMethodsFrom()` are not read; `exportPattern()` character classes use ASCII semantics; S4 `contains=` links only to classes defined in the repository or the `VIRTUAL` marker, so basic-type bases add no edge; imports of external (CRAN) packages produce no edges; an edit to NAMESPACE alone is not re-resolved by an incremental re-index, so run a full analyze after changing it; no framework or entry-point detection. ## Agent Skills