c118996746
- 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
340 lines
12 KiB
Plaintext
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 |