Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions understand-anything-plugin/packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"tree-sitter-go": "^0.25.0",
"tree-sitter-java": "^0.23.5",
"tree-sitter-javascript": "^0.25.0",
"tree-sitter-objc": "3.0.2",
"tree-sitter-php": "^0.23.11",
"tree-sitter-python": "^0.25.0",
"tree-sitter-ruby": "^0.23.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ describe("LanguageRegistry", () => {
});

describe("createDefault", () => {
it("registers all 41 built-in language configs", () => {
it("registers all 42 built-in language configs", () => {
const registry = LanguageRegistry.createDefault();
const all = registry.getAllLanguages();
expect(all.length).toBe(41);
expect(all.length).toBe(42);
});

it("maps all expected extensions", () => {
Expand All @@ -72,6 +72,8 @@ describe("LanguageRegistry", () => {
expect(registry.getByExtension(".h")?.id).toBe("c");
expect(registry.getByExtension(".lua")?.id).toBe("lua");
expect(registry.getByExtension(".js")?.id).toBe("javascript");
expect(registry.getByExtension(".m")?.id).toBe("objective-c");
expect(registry.getByExtension(".mm")?.id).toBe("objective-c");
});

it("registers Swift with tree-sitter grammar metadata", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { cppConfig } from "./cpp.js";
import { dartConfig } from "./dart.js";
import { csharpConfig } from "./csharp.js";
import { luaConfig } from "./lua.js";
import { objectivecConfig } from "./objectivec.js";
// Non-code language configs
import { markdownConfig } from "./markdown.js";
import { yamlConfig } from "./yaml.js";
Expand Down Expand Up @@ -55,6 +56,7 @@ export const builtinLanguageConfigs: LanguageConfig[] = [
swiftConfig,
kotlinConfig,
luaConfig,
objectivecConfig,
cConfig,
cppConfig,
dartConfig,
Expand Down Expand Up @@ -101,6 +103,7 @@ export {
swiftConfig,
kotlinConfig,
luaConfig,
objectivecConfig,
cConfig,
cppConfig,
dartConfig,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { LanguageConfig } from "../types.js";

export const objectivecConfig = {
id: "objective-c",
displayName: "Objective-C",
extensions: [".m", ".mm"],
treeSitter: {
wasmPackage: "tree-sitter-objc",
wasmFile: "tree-sitter-objc.wasm",
},
concepts: [
"message sending",
"protocols",
"categories",
"class extensions",
"property attributes",
"ARC memory management",
"blocks",
"dynamic dispatch",
"key-value observing",
"Objective-C runtime",
],
filePatterns: {
entryPoints: ["main.m", "AppDelegate.m"],
barrels: [],
tests: ["*Tests.m", "*Spec.m", "Tests/**/*.m"],
config: ["Podfile", "*.xcodeproj", "*.xcworkspace"],
},
} satisfies LanguageConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Scratch test: Can tree-sitter-cpp grammar parse Objective-C syntax?
*
* This answers the question: "Can we just reuse CppExtractor for ObjC?"
*/
import { describe, it, expect, beforeAll } from "vitest";
import { createRequire } from "node:module";
import { CppExtractor } from "../cpp-extractor.js";

const require = createRequire(import.meta.url);

let Parser: any;
let Language: any;
let cppLang: any;

beforeAll(async () => {
const mod = await import("web-tree-sitter");
Parser = mod.Parser;
Language = mod.Language;
await Parser.init();
const wasmPath = require.resolve("tree-sitter-cpp/tree-sitter-cpp.wasm");
cppLang = await Language.load(wasmPath);
});

function parse(code: string) {
const parser = new Parser();
parser.setLanguage(cppLang);
const tree = parser.parse(code);
return { tree, parser, root: tree.rootNode };
}

const OBJC_CODE = `
#import <Foundation/Foundation.h>
#import "DataService.h"

@interface SomeManager : NSObject
@property (nonatomic, strong) NSString *name;
- (void)loadData;
+ (SomeManager *)sharedInstance;
@end

@implementation SomeManager
+ (SomeManager *)sharedInstance {
static SomeManager *instance = nil;
return instance;
}
- (void)loadData {
NSLog(@"loading");
}
@end
`;

describe("Can tree-sitter-cpp parse Objective-C?", () => {
const extractor = new CppExtractor();

it("tree-sitter-cpp produces ERROR nodes when parsing @interface/@implementation", () => {
const { tree, parser, root } = parse(OBJC_CODE);
const rootStr = root.toString();
console.log("AST root:", rootStr.slice(0, 500));
// ObjC syntax (@interface, @implementation, message sends) is NOT valid C++
// The parser will produce ERROR nodes, confirming it can't handle ObjC
const hasErrors = rootStr.includes("ERROR");
expect(hasErrors).toBe(true); // C++ grammar chokes on ObjC syntax
tree.delete();
parser.delete();
});

it("CppExtractor.extractStructure produces empty results for ObjC code (even with cpp grammar)", () => {
const { tree, parser, root } = parse(OBJC_CODE);
const result = extractor.extractStructure(root);
console.log("Functions found:", result.functions.map(f => f.name));
console.log("Classes found:", result.classes.map(c => c.name));
// The CppExtractor won't find @interface/@implementation as classes,
// and won't find - (void)method: signatures as functions
expect(result.classes).toHaveLength(0); // confirms we CANNOT reuse CppExtractor
expect(result.functions).toHaveLength(0);
tree.delete();
parser.delete();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#import <AVFoundation/AVFoundation.h>
#import <vector>
#import <string>

/// Hybrid audio processor — mixes Objective-C with C++ for audio DSP.
/// Handles audio buffer processing with SIMD optimizations via Accelerate
/// framework and raw C++ vector operations.
@interface AudioProcessor : NSObject {
@public
std::vector<float> _sampleBuffer;
}

@property (nonatomic, assign) float gain;
@property (nonatomic, assign, readonly) NSUInteger sampleCount;
@property (nonatomic, strong) AVAudioEngine *audioEngine;

+ (instancetype)processorWithSampleRate:(double)sampleRate;

- (void)processBuffer:(AVAudioPCMBuffer *)buffer;
- (std::vector<float>)extractSamplesFromBuffer:(AVAudioPCMBuffer *)buffer;
- (void)applyGainToSamples:(std::vector<float> &)samples;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#import "AudioProcessor.h"
#import <Accelerate/Accelerate.h>
#import <algorithm>

@implementation AudioProcessor

+ (instancetype)processorWithSampleRate:(double)sampleRate {
AudioProcessor *processor = [[AudioProcessor alloc] init];
processor.audioEngine = [[AVAudioEngine alloc] init];
processor.gain = 1.0f;
return processor;
}

- (std::vector<float>)extractSamplesFromBuffer:(AVAudioPCMBuffer *)buffer {
std::vector<float> samples;
AVAudioFrameCount frameCount = buffer.frameLength;

if (frameCount == 0) return samples;

samples.resize(frameCount);
float *channelData = buffer.floatChannelData[0];
memcpy(samples.data(), channelData, frameCount * sizeof(float));

return samples;
}

- (void)applyGainToSamples:(std::vector<float> &)samples {
float scalar = self.gain;
vDSP_vsmul(samples.data(), 1, &scalar, samples.data(), 1, samples.size());
}

- (void)processBuffer:(AVAudioPCMBuffer *)buffer {
auto samples = [self extractSamplesFromBuffer:buffer];
[self applyGainToSamples:samples];

// C++ algorithm: clamp to [-1.0, 1.0]
std::transform(samples.begin(), samples.end(), samples.begin(), [](float s) {
return std::max(-1.0f, std::min(1.0f, s));
});

NSUInteger count = samples.size();
_sampleBuffer = std::move(samples);
_sampleCount = count;

NSLog(@"Processed %lu samples with gain %.2f", (unsigned long)count, self.gain);
}

- (NSUInteger)sampleCount {
return _sampleBuffer.size();
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#import <Foundation/Foundation.h>

/// Core data service — handles network requests, caching, and data pipelines
/// for the entire application. This is the primary entry point for all data
/// operations.
@protocol DataServiceDelegate;

@interface DataService : NSObject

@property (nonatomic, strong, readonly) NSURLSession *session;
@property (nonatomic, assign) BOOL isOnline;
@property (nonatomic, weak) id<DataServiceDelegate> delegate;

// Lifecycle
- (instancetype)initWithConfiguration:(NSDictionary *)config;
+ (instancetype)sharedService;

// Data fetching
- (void)fetchItemsWithCompletion:(void (^)(NSArray *items, NSError *error))completion;
- (void)fetchItemWithID:(NSString *)itemID completion:(void (^)(id item, NSError *error))completion;

// Multi-part selector
- (NSArray *)filterItems:(NSArray *)rawItems
withCriteria:(NSDictionary *)criteria
sortedBy:(NSString *)sortKey;

// Batch operations
- (void)batchUpdateItems:(NSArray *)items
withHandler:(void (^)(BOOL success, NSInteger updatedCount))handler;

@end

@protocol DataServiceDelegate <NSObject>

@required
- (void)dataServiceDidConnect:(DataService *)service;
- (void)dataService:(DataService *)service didFailWithError:(NSError *)error;

@optional
- (void)dataServiceDidGoOffline:(DataService *)service;

@end
Loading