feat: Add PHP inheritance extraction and improve method call handling
Addresses PHP's base_clause syntax for class inheritance (extends) and implements clause for interface implementation. Adds trait_declaration support and separates property_declaration into fieldTypes. Improves PHP method call extraction by handling member_call_expression and scoped_call_expression with proper receiver name processing, including $ prefix stripping and self/this/parent/static receiver filtering.
This commit is contained in:
@@ -4,7 +4,7 @@ import type { LanguageExtractor } from '../tree-sitter-types';
|
||||
|
||||
export const phpExtractor: LanguageExtractor = {
|
||||
functionTypes: ['function_definition'],
|
||||
classTypes: ['class_declaration'],
|
||||
classTypes: ['class_declaration', 'trait_declaration'],
|
||||
methodTypes: ['method_declaration'],
|
||||
interfaceTypes: ['interface_declaration'],
|
||||
structTypes: [],
|
||||
@@ -13,7 +13,8 @@ export const phpExtractor: LanguageExtractor = {
|
||||
typeAliasTypes: [],
|
||||
importTypes: ['namespace_use_declaration'],
|
||||
callTypes: ['function_call_expression', 'member_call_expression', 'scoped_call_expression'],
|
||||
variableTypes: ['property_declaration', 'const_declaration'],
|
||||
variableTypes: ['const_declaration'],
|
||||
fieldTypes: ['property_declaration'],
|
||||
nameField: 'name',
|
||||
bodyField: 'body',
|
||||
paramsField: 'parameters',
|
||||
|
||||
@@ -1151,17 +1151,25 @@ export class TreeSitterExtractor {
|
||||
let calleeName = '';
|
||||
|
||||
// Java/Kotlin method_invocation has 'object' + 'name' fields instead of 'function'
|
||||
// PHP member_call_expression has 'object' + 'name', scoped_call_expression has 'scope' + 'name'
|
||||
const nameField = getChildByField(node, 'name');
|
||||
const objectField = getChildByField(node, 'object');
|
||||
const objectField = getChildByField(node, 'object') || getChildByField(node, 'scope');
|
||||
|
||||
if (nameField && objectField && node.type === 'method_invocation') {
|
||||
// Java-style method call: receiver.method()
|
||||
if (nameField && objectField && (node.type === 'method_invocation' || node.type === 'member_call_expression' || node.type === 'scoped_call_expression')) {
|
||||
// Method call with explicit receiver: receiver.method() / $receiver->method() / ClassName::method()
|
||||
const methodName = getNodeText(nameField, this.source);
|
||||
const receiverName = getNodeText(objectField, this.source);
|
||||
let receiverName = getNodeText(objectField, this.source);
|
||||
// Strip PHP $ prefix from variable names
|
||||
receiverName = receiverName.replace(/^\$/, '');
|
||||
|
||||
if (methodName) {
|
||||
// Emit receiver.method form for qualified resolution
|
||||
calleeName = `${receiverName}.${methodName}`;
|
||||
// Skip self/this/parent/static receivers — they don't aid resolution
|
||||
const SKIP_RECEIVERS = new Set(['self', 'this', 'cls', 'super', 'parent', 'static']);
|
||||
if (SKIP_RECEIVERS.has(receiverName)) {
|
||||
calleeName = methodName;
|
||||
} else {
|
||||
calleeName = `${receiverName}.${methodName}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const func = getChildByField(node, 'function') || node.namedChild(0);
|
||||
@@ -1245,6 +1253,7 @@ export class TreeSitterExtractor {
|
||||
if (
|
||||
child.type === 'extends_clause' ||
|
||||
child.type === 'superclass' ||
|
||||
child.type === 'base_clause' || // PHP class extends
|
||||
child.type === 'extends_interfaces' // Java interface extends
|
||||
) {
|
||||
// Extract parent class/interface names
|
||||
|
||||
Reference in New Issue
Block a user