|
@@ -52,6 +52,10 @@
|
|
|
//! per-caller targets (insertion-ordered, branch reassignments accumulate);
|
|
//! per-caller targets (insertion-ordered, branch reassignments accumulate);
|
|
|
//! a later bare `k(args)` emits one `calls` ref PER target and suppresses
|
|
//! a later bare `k(args)` emits one `calls` ref PER target and suppresses
|
|
|
//! the local name. Template args stripped like base-class refs (#1043).
|
|
//! the local name. Template args stripped like base-class refs (#1043).
|
|
|
|
|
+//! - pure-virtual methods (#1727): cpp in-class `virtual T f(...) = 0;` is a
|
|
|
|
|
+//! `field_declaration` (not `function_definition`); mint a method node so
|
|
|
|
|
+//! abstract-base calls and cpp-override synthesis have a target. Mirrors
|
|
|
|
|
+//! TS `methodTypes` + `classifyMethodNode` / `isAbstract`.
|
|
|
//! - stack construction (#1035): cpp `declaration` with class-like named
|
|
//! - stack construction (#1035): cpp `declaration` with class-like named
|
|
|
//! `type` and an init_declarator whose value is argument_list /
|
|
//! `type` and an init_declarator whose value is argument_list /
|
|
|
//! initializer_list → `instantiates` (most-vexing-parse excluded).
|
|
//! initializer_list → `instantiates` (most-vexing-parse excluded).
|
|
@@ -66,7 +70,7 @@
|
|
|
|
|
|
|
|
use crate::buffers::{
|
|
use crate::buffers::{
|
|
|
build_meta, edge_kind_index, node_kind_index, Arena, BoolFlags, EdgeRow, EmitOut, NodeRow,
|
|
build_meta, edge_kind_index, node_kind_index, Arena, BoolFlags, EdgeRow, EmitOut, NodeRow,
|
|
|
- RefRow, StrRef, Tables, FLAG_IS_EXPORTED, FUNCTION_REF_CODE, NONE, NONE_STR,
|
|
|
|
|
|
|
+ RefRow, StrRef, Tables, FLAG_IS_ABSTRACT, FLAG_IS_EXPORTED, FUNCTION_REF_CODE, NONE, NONE_STR,
|
|
|
};
|
|
};
|
|
|
use crate::docstring::preceding_docstring;
|
|
use crate::docstring::preceding_docstring;
|
|
|
use crate::ids;
|
|
use crate::ids;
|
|
@@ -289,6 +293,7 @@ struct Extra {
|
|
|
signature: Option<String>,
|
|
signature: Option<String>,
|
|
|
visibility: Option<u8>,
|
|
visibility: Option<u8>,
|
|
|
is_exported: Option<bool>,
|
|
is_exported: Option<bool>,
|
|
|
|
|
+ is_abstract: Option<bool>,
|
|
|
return_type: Option<String>,
|
|
return_type: Option<String>,
|
|
|
qualified_name: Option<String>,
|
|
qualified_name: Option<String>,
|
|
|
}
|
|
}
|
|
@@ -508,6 +513,9 @@ impl<'t> Walker<'t> {
|
|
|
if let Some(v) = extra.is_exported {
|
|
if let Some(v) = extra.is_exported {
|
|
|
flags.set(FLAG_IS_EXPORTED, v);
|
|
flags.set(FLAG_IS_EXPORTED, v);
|
|
|
}
|
|
}
|
|
|
|
|
+ if let Some(v) = extra.is_abstract {
|
|
|
|
|
+ flags.set(FLAG_IS_ABSTRACT, v);
|
|
|
|
|
+ }
|
|
|
let name_ref = self.arena.put(name);
|
|
let name_ref = self.arena.put(name);
|
|
|
let qn_ref = self.arena.put(&qualified);
|
|
let qn_ref = self.arena.put(&qualified);
|
|
|
let id_ref = self.arena.put(&id);
|
|
let id_ref = self.arena.put(&id);
|
|
@@ -740,6 +748,36 @@ impl<'t> Walker<'t> {
|
|
|
.any(|c| c.kind() == "type_qualifier" && self.text(c) == "const")
|
|
.any(|c| c.kind() == "type_qualifier" && self.text(c) == "const")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// `#1727`: C++ pure-virtual method declaration (`virtual int read(int key) = 0;`).
|
|
|
|
|
+ /// tree-sitter-cpp shapes these as `field_declaration` whose declarator unwraps
|
|
|
|
|
+ /// to a `function_declarator`, with the pure-virtual `= 0` as a DIRECT
|
|
|
|
|
+ /// `number_literal` "0" child (default-arg `= 0` lives inside
|
|
|
|
|
+ /// `parameter_declaration` and must not match).
|
|
|
|
|
+ fn is_cpp_pure_virtual_method_decl(&self, node: Node<'_>) -> bool {
|
|
|
|
|
+ if node.kind() != "field_declaration" {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ let Some(mut declarator) = node.child_by_field_name("declarator") else {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ };
|
|
|
|
|
+ while matches!(declarator.kind(), "pointer_declarator" | "reference_declarator") {
|
|
|
|
|
+ let inner = declarator
|
|
|
|
|
+ .child_by_field_name("declarator")
|
|
|
|
|
+ .or_else(|| declarator.named_child(0));
|
|
|
|
|
+ let Some(inner) = inner else {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ };
|
|
|
|
|
+ declarator = inner;
|
|
|
|
|
+ }
|
|
|
|
|
+ if declarator.kind() != "function_declarator" {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ (0..node.named_child_count())
|
|
|
|
|
+ .filter_map(|i| node.named_child(i))
|
|
|
|
|
+ .any(|c| c.kind() == "number_literal" && self.text(c) == "0")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
/// cppExtractor.isMisparsedFunction (languages/c-cpp.ts:811). cpp only.
|
|
/// cppExtractor.isMisparsedFunction (languages/c-cpp.ts:811). cpp only.
|
|
|
fn is_misparsed_function(&self, name: &str, node: Node) -> bool {
|
|
fn is_misparsed_function(&self, name: &str, node: Node) -> bool {
|
|
|
if self.variant != Variant::Cpp {
|
|
if self.variant != Variant::Cpp {
|
|
@@ -830,6 +868,17 @@ impl<'t> Walker<'t> {
|
|
|
self.extract_variable(node);
|
|
self.extract_variable(node);
|
|
|
self.scan_fn_ref_subtree(node, 0);
|
|
self.scan_fn_ref_subtree(node, 0);
|
|
|
skip_children = true;
|
|
skip_children = true;
|
|
|
|
|
+ } else if self.variant == Variant::Cpp
|
|
|
|
|
+ && kind == "field_declaration"
|
|
|
|
|
+ && self.inside_class_like()
|
|
|
|
|
+ && self.is_cpp_pure_virtual_method_decl(node)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Pure-virtual methods have no `function_definition` body — mint the
|
|
|
|
|
+ // method node so calls through the abstract base and cpp-override
|
|
|
|
|
+ // synthesis have a target (#1727). Non-pure field_declarations fall
|
|
|
|
|
+ // through to the children walk (data members / prototypes).
|
|
|
|
|
+ self.extract_method(node);
|
|
|
|
|
+ skip_children = true;
|
|
|
} else if kind == "preproc_include" {
|
|
} else if kind == "preproc_include" {
|
|
|
self.extract_import(node);
|
|
self.extract_import(node);
|
|
|
} else if kind == "call_expression" {
|
|
} else if kind == "call_expression" {
|
|
@@ -914,6 +963,11 @@ impl<'t> Walker<'t> {
|
|
|
let extra = Extra {
|
|
let extra = Extra {
|
|
|
docstring: preceding_docstring(node, self.src),
|
|
docstring: preceding_docstring(node, self.src),
|
|
|
visibility: if self.variant == Variant::Cpp { self.visibility_of(node) } else { None },
|
|
visibility: if self.variant == Variant::Cpp { self.visibility_of(node) } else { None },
|
|
|
|
|
+ is_abstract: if self.variant == Variant::Cpp && self.is_cpp_pure_virtual_method_decl(node) {
|
|
|
|
|
+ Some(true)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ None
|
|
|
|
|
+ },
|
|
|
return_type: self.return_type_of(node),
|
|
return_type: self.return_type_of(node),
|
|
|
qualified_name: receiver_type
|
|
qualified_name: receiver_type
|
|
|
.as_ref()
|
|
.as_ref()
|