mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-21 16:57:09 +08:00
3273f20f47
Inside an Objective-C @implementation, tree-sitter-objc wraps each method, function and declaration in an implementation_definition of its own, and the comment above it is the wrapper's sibling, not the method's. getPrecedingDocstring looked only at the method's own siblings, so no method, function or static written in an @implementation had its doc comment, while the same comment above an @interface property was read. - tree-sitter-helpers.ts: implementation_definition joins DOCSTRING_WRAPPER_TYPES. Each wraps exactly one item, so the climb cannot hand a comment to a neighbour: a comment above an @synthesize stays its own. - codegraph-kernel docstring.rs: the faithful port's wrapper list gains it too. The kernel does not walk Objective-C, so the entry only keeps the two lists alike. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
/**
|
|
* Inside an Objective-C `@implementation`, the parser wraps each method,
|
|
* function and declaration in an `implementation_definition` of its own, and
|
|
* the comment above it is that wrapper's sibling, not the method's. So no
|
|
* method, function or static written in an `@implementation` had its doc
|
|
* comment, while the same comment above an `@interface` property was read.
|
|
* The wrapper is now climbed like an `export` statement's.
|
|
*/
|
|
import { describe, it, expect, beforeAll } from 'vitest';
|
|
import { extractFromSource } from '../src/extraction';
|
|
import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars';
|
|
|
|
describe('a doc comment inside an Objective-C @implementation', () => {
|
|
beforeAll(async () => {
|
|
await initGrammars();
|
|
await loadGrammarsForLanguages(['objc']);
|
|
});
|
|
|
|
for (const crlf of [false, true]) {
|
|
const eol = (s: string) => (crlf ? s.replace(/\n/g, '\r\n') : s);
|
|
const label = crlf ? ' (CRLF)' : '';
|
|
|
|
it(`documents the method, function or static below it${label}`, () => {
|
|
const source = [
|
|
'@interface Tests : NSObject',
|
|
'/** The number of runs. */',
|
|
'@property (nonatomic) int runs;',
|
|
'@end',
|
|
'',
|
|
'@implementation Tests',
|
|
'',
|
|
'/** Flags the callbacks set. */',
|
|
'static struct {',
|
|
' int calls;',
|
|
'} g_callbackData;',
|
|
'',
|
|
'/** Runs it. */',
|
|
'- (void)testIt {',
|
|
'}',
|
|
'',
|
|
'// A helper.',
|
|
'static void helper(void) {',
|
|
'}',
|
|
'',
|
|
'/**',
|
|
' * The shared instance.',
|
|
' */',
|
|
'+ (instancetype)shared {',
|
|
' return nil;',
|
|
'}',
|
|
'',
|
|
'/** Synthesized. */',
|
|
'@synthesize runs = _runs;',
|
|
'',
|
|
'- (void)undocumented {',
|
|
'}',
|
|
'',
|
|
'@end',
|
|
'',
|
|
].join('\n');
|
|
const result = extractFromSource('src/Tests.m', eol(source), 'objc');
|
|
const docs = result.nodes
|
|
.filter((n) => n.kind !== 'file' && n.kind !== 'class')
|
|
.map((n) => `${n.kind} ${n.qualifiedName}: ${n.docstring ?? '-'}`);
|
|
expect(docs).toEqual([
|
|
'property Tests::runs: The number of runs.',
|
|
'struct Tests::g_callbackData: Flags the callbacks set.',
|
|
'method Tests::testIt: Runs it.',
|
|
'function Tests::helper: A helper.',
|
|
'method Tests::shared: The shared instance.',
|
|
'method Tests::undocumented: -',
|
|
]);
|
|
});
|
|
}
|
|
});
|