Files
CxIDE/Core/SwiftEngineWrapper.mm
T
cx-git-agent c118996746 feat: CxIDE v1 — native macOS SwiftUI IDE with agentic AI assistant
- SwiftUI macOS app with C++17 code analysis engine (ObjC++ bridge)
- Agentic AI loop: LLM plans → tool calls → execution → feedback loop
- 15 agent tools: file ops, terminal, git, xcode build, code intel
- 7 persistent terminal tools with background session management
- Chat sidebar with agent step rendering and auto-apply
- NVIDIA NIM API integration (Llama 3.3 70B default)
- OpenAI tool_calls format with prompt-based fallback
- Code editor with syntax highlighting and multi-tab support
- File tree, console view, terminal view
- Git integration and workspace management
2026-04-21 16:05:52 -05:00

340 lines
12 KiB
Plaintext

#import "SwiftEngineWrapper.h"
#import "CodeEngine.hpp"
#include <vector>
#include <string>
@implementation SwiftEngineWrapper {
CodeEngine *_cppEngine;
}
- (instancetype)init {
self = [super init];
if (self) {
_cppEngine = new CodeEngine();
}
return self;
}
- (void)dealloc {
delete _cppEngine;
}
// ─── Configuration ───────────────────────────────────────────────
- (void)setMaxLineLength:(NSInteger)length {
auto config = _cppEngine->get_config();
config.maxLineLength = static_cast<int>(length);
_cppEngine->set_config(config);
}
- (void)setMaxNestingDepth:(NSInteger)depth {
auto config = _cppEngine->get_config();
config.maxNestingDepth = static_cast<int>(depth);
_cppEngine->set_config(config);
}
- (void)setMaxFunctionLength:(NSInteger)length {
auto config = _cppEngine->get_config();
config.maxFunctionLength = static_cast<int>(length);
_cppEngine->set_config(config);
}
- (void)setMinCommentRatio:(double)ratio {
auto config = _cppEngine->get_config();
config.minCommentRatio = ratio;
_cppEngine->set_config(config);
}
- (void)setDetectForceUnwraps:(BOOL)enabled {
auto config = _cppEngine->get_config();
config.detectForceUnwraps = enabled;
_cppEngine->set_config(config);
}
- (void)setDetectForceTry:(BOOL)enabled {
auto config = _cppEngine->get_config();
config.detectForceTry = enabled;
_cppEngine->set_config(config);
}
- (void)setDetectForceCast:(BOOL)enabled {
auto config = _cppEngine->get_config();
config.detectForceCast = enabled;
_cppEngine->set_config(config);
}
- (void)setDetectDuplicateLines:(BOOL)enabled {
auto config = _cppEngine->get_config();
config.detectDuplicateLines = enabled;
_cppEngine->set_config(config);
}
- (void)setDetectTodoFixme:(BOOL)enabled {
auto config = _cppEngine->get_config();
config.detectTodoFixme = enabled;
_cppEngine->set_config(config);
}
- (void)setDetectRetainCycles:(BOOL)enabled {
auto config = _cppEngine->get_config();
config.detectRetainCycles = enabled;
_cppEngine->set_config(config);
}
// ─── Full Analysis ───────────────────────────────────────────────
- (NSString *)runAnalysis:(NSString *)code {
std::string stdCode = std::string([code UTF8String]);
std::string result = _cppEngine->analyze_syntax(stdCode);
return [NSString stringWithUTF8String:result.c_str()];
}
- (NSDictionary<NSString *, id> *)runStructuredAnalysis:(NSString *)code {
auto report = _cppEngine->full_analysis(std::string([code UTF8String]));
// Convert symbols
NSMutableArray *symbolsArray = [NSMutableArray array];
for (const auto& sym : report.symbols) {
NSString *kindStr;
switch (sym.kind) {
case SymbolKind::Function: kindStr = @"function"; break;
case SymbolKind::Class: kindStr = @"class"; break;
case SymbolKind::Struct: kindStr = @"struct"; break;
case SymbolKind::Enum: kindStr = @"enum"; break;
case SymbolKind::Protocol: kindStr = @"protocol"; break;
case SymbolKind::Variable: kindStr = @"variable"; break;
case SymbolKind::Constant: kindStr = @"constant"; break;
case SymbolKind::TypeAlias: kindStr = @"typealias"; break;
case SymbolKind::Extension: kindStr = @"extension"; break;
}
[symbolsArray addObject:@{
@"kind": kindStr,
@"name": [NSString stringWithUTF8String:sym.name.c_str()],
@"line": @(sym.line),
@"access": [NSString stringWithUTF8String:sym.accessLevel.c_str()],
@"signature": [NSString stringWithUTF8String:sym.signature.c_str()]
}];
}
// Convert imports
NSMutableArray *importsArray = [NSMutableArray array];
for (const auto& imp : report.imports) {
[importsArray addObject:[NSString stringWithUTF8String:imp.c_str()]];
}
// Convert keywords
NSMutableArray *keywordsArray = [NSMutableArray array];
for (const auto& kw : report.keywords) {
[keywordsArray addObject:[NSString stringWithUTF8String:kw.c_str()]];
}
// Convert issues
NSMutableArray *issuesArray = [NSMutableArray array];
for (const auto& issue : report.issues) {
[issuesArray addObject:[NSString stringWithUTF8String:issue.c_str()]];
}
// Convert keyword frequency
NSMutableDictionary *freqDict = [NSMutableDictionary dictionary];
for (const auto& pair : report.keywordFrequency) {
freqDict[[NSString stringWithUTF8String:pair.first.c_str()]] = @(pair.second);
}
// Convert duplicate pairs
NSMutableArray *dupesArray = [NSMutableArray array];
for (const auto& pair : report.duplicateLinePairs) {
[dupesArray addObject:@{@"lineA": @(pair.first), @"lineB": @(pair.second)}];
}
// Convert TODOs
NSMutableArray *todosArray = [NSMutableArray array];
for (const auto& todo : report.todoComments) {
[todosArray addObject:@{
@"line": @(todo.first),
@"text": [NSString stringWithUTF8String:todo.second.c_str()]
}];
}
return @{
@"lineCount": @(report.lineCount),
@"charCount": @(report.charCount),
@"blankLineCount": @(report.blankLineCount),
@"codeLineCount": @(report.codeLineCount),
@"commentLineCount": @(report.commentLineCount),
@"functionCount": @(report.functionCount),
@"classCount": @(report.classCount),
@"structCount": @(report.structCount),
@"enumCount": @(report.enumCount),
@"protocolCount": @(report.protocolCount),
@"complexity": [NSString stringWithUTF8String:report.complexity.c_str()],
@"cyclomaticComplexity": @(report.cyclomaticComplexity),
@"maintainabilityIndex": @(report.maintainabilityIndex),
@"bracesBalanced": @(report.bracesBalanced),
@"commentRatio": @(report.commentRatio),
@"keywords": [keywordsArray copy],
@"issues": [issuesArray copy],
@"keywordFrequency": [freqDict copy],
@"symbols": [symbolsArray copy],
@"imports": [importsArray copy],
@"duplicateLinePairs": [dupesArray copy],
@"todoComments": [todosArray copy]
};
}
// ─── Counting ────────────────────────────────────────────────────
- (NSInteger)getChecksum:(NSString *)code {
return _cppEngine->calculate_checksum(std::string([code UTF8String]));
}
- (NSInteger)countLines:(NSString *)code {
return _cppEngine->count_lines(std::string([code UTF8String]));
}
- (NSInteger)countBlankLines:(NSString *)code {
return _cppEngine->count_blank_lines(std::string([code UTF8String]));
}
- (NSInteger)countCodeLines:(NSString *)code {
return _cppEngine->count_code_lines(std::string([code UTF8String]));
}
- (NSInteger)countFunctions:(NSString *)code {
return _cppEngine->count_functions(std::string([code UTF8String]));
}
- (NSInteger)countClasses:(NSString *)code {
return _cppEngine->count_classes(std::string([code UTF8String]));
}
- (NSInteger)countStructs:(NSString *)code {
return _cppEngine->count_structs(std::string([code UTF8String]));
}
- (NSInteger)countEnums:(NSString *)code {
return _cppEngine->count_enums(std::string([code UTF8String]));
}
- (NSInteger)countProtocols:(NSString *)code {
return _cppEngine->count_protocols(std::string([code UTF8String]));
}
- (NSInteger)countPattern:(NSString *)code pattern:(NSString *)pattern {
return _cppEngine->count_pattern(
std::string([code UTF8String]),
std::string([pattern UTF8String])
);
}
// ─── Analysis ────────────────────────────────────────────────────
- (NSString *)estimateComplexity:(NSString *)code {
std::string result = _cppEngine->estimate_complexity(std::string([code UTF8String]));
return [NSString stringWithUTF8String:result.c_str()];
}
- (NSInteger)cyclomaticComplexity:(NSString *)code {
return _cppEngine->cyclomatic_complexity(std::string([code UTF8String]));
}
- (double)maintainabilityIndex:(NSString *)code {
return _cppEngine->maintainability_index(std::string([code UTF8String]));
}
- (BOOL)checkBalancedBraces:(NSString *)code {
return _cppEngine->check_balanced_braces(std::string([code UTF8String]));
}
- (NSArray<NSString *> *)extractKeywords:(NSString *)code {
auto keywords = _cppEngine->extract_keywords(std::string([code UTF8String]));
NSMutableArray *result = [NSMutableArray arrayWithCapacity:keywords.size()];
for (const auto& kw : keywords) {
[result addObject:[NSString stringWithUTF8String:kw.c_str()]];
}
return [result copy];
}
- (NSArray<NSString *> *)findIssues:(NSString *)code {
auto issues = _cppEngine->find_issues(std::string([code UTF8String]));
NSMutableArray *result = [NSMutableArray arrayWithCapacity:issues.size()];
for (const auto& issue : issues) {
[result addObject:[NSString stringWithUTF8String:issue.c_str()]];
}
return [result copy];
}
- (double)commentRatio:(NSString *)code {
return _cppEngine->comment_ratio(std::string([code UTF8String]));
}
// ─── Symbol & Import Extraction ──────────────────────────────────
- (NSArray<NSDictionary<NSString *, id> *> *)extractSymbols:(NSString *)code {
auto symbols = _cppEngine->extract_symbols(std::string([code UTF8String]));
NSMutableArray *result = [NSMutableArray arrayWithCapacity:symbols.size()];
for (const auto& sym : symbols) {
NSString *kindStr;
switch (sym.kind) {
case SymbolKind::Function: kindStr = @"function"; break;
case SymbolKind::Class: kindStr = @"class"; break;
case SymbolKind::Struct: kindStr = @"struct"; break;
case SymbolKind::Enum: kindStr = @"enum"; break;
case SymbolKind::Protocol: kindStr = @"protocol"; break;
case SymbolKind::Variable: kindStr = @"variable"; break;
case SymbolKind::Constant: kindStr = @"constant"; break;
case SymbolKind::TypeAlias: kindStr = @"typealias"; break;
case SymbolKind::Extension: kindStr = @"extension"; break;
}
[result addObject:@{
@"kind": kindStr,
@"name": [NSString stringWithUTF8String:sym.name.c_str()],
@"line": @(sym.line),
@"access": [NSString stringWithUTF8String:sym.accessLevel.c_str()],
@"signature": [NSString stringWithUTF8String:sym.signature.c_str()]
}];
}
return [result copy];
}
- (NSArray<NSString *> *)extractImports:(NSString *)code {
auto imports = _cppEngine->extract_imports(std::string([code UTF8String]));
NSMutableArray *result = [NSMutableArray arrayWithCapacity:imports.size()];
for (const auto& imp : imports) {
[result addObject:[NSString stringWithUTF8String:imp.c_str()]];
}
return [result copy];
}
// ─── Duplicate & TODO Detection ──────────────────────────────────
- (NSArray<NSDictionary<NSString *, NSNumber *> *> *)detectDuplicateLines:(NSString *)code {
auto dupes = _cppEngine->detect_duplicate_lines(std::string([code UTF8String]));
NSMutableArray *result = [NSMutableArray arrayWithCapacity:dupes.size()];
for (const auto& pair : dupes) {
[result addObject:@{@"lineA": @(pair.first), @"lineB": @(pair.second)}];
}
return [result copy];
}
- (NSArray<NSDictionary<NSString *, id> *> *)extractTodoComments:(NSString *)code {
auto todos = _cppEngine->extract_todo_comments(std::string([code UTF8String]));
NSMutableArray *result = [NSMutableArray arrayWithCapacity:todos.size()];
for (const auto& todo : todos) {
[result addObject:@{
@"line": @(todo.first),
@"text": [NSString stringWithUTF8String:todo.second.c_str()]
}];
}
return [result copy];
}
// ─── Indentation ────────────────────────────────────────────────
- (NSInteger)suggestIndentation:(NSString *)codeBefore tabWidth:(NSInteger)tabWidth {
return _cppEngine->suggest_indentation(
std::string([codeBefore UTF8String]),
static_cast<int>(tabWidth)
);
}
@end