Skip to content

Commit 7855af0

Browse files
committed
refactor into modules and files
1 parent 6663f6a commit 7855af0

File tree

6 files changed

+318
-221
lines changed

6 files changed

+318
-221
lines changed

src/analyze/swift/constants.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Constants and helper-return collectors for Swift fixtures
3+
* - Scans directory for top-level lets and enum/struct static lets
4+
* - Extracts simple function returns for dict/array builders
5+
*/
6+
7+
const fs = require('fs');
8+
const path = require('path');
9+
10+
function buildCrossFileConstMap(dir) {
11+
const map = {};
12+
try {
13+
const entries = fs.readdirSync(dir).filter(f => f.endsWith('.swift'));
14+
for (const f of entries) {
15+
const fp = path.join(dir, f);
16+
const content = fs.readFileSync(fp, 'utf8');
17+
// Top-level: let NAME = "..."
18+
for (const m of content.matchAll(/\blet\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*"([\s\S]*?)"/g)) {
19+
map[m[1]] = m[2];
20+
}
21+
// Enum/struct blocks: capture namespace and all static lets inside
22+
let idx = 0;
23+
while (idx < content.length) {
24+
const head = content.slice(idx);
25+
const mm = /\b(enum|struct)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/m.exec(head);
26+
if (!mm) break;
27+
const ns = mm[2];
28+
const blockStart = idx + mm.index + mm[0].length - 1; // position at '{'
29+
// Find matching closing brace
30+
let depth = 0; let end = -1;
31+
for (let i = blockStart; i < content.length; i++) {
32+
const ch = content[i];
33+
if (ch === '{') depth++;
34+
else if (ch === '}') { depth--; if (depth === 0) { end = i; break; } }
35+
}
36+
if (end === -1) break;
37+
const block = content.slice(blockStart + 1, end);
38+
for (const sm of block.matchAll(/\bstatic\s+let\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*"([\s\S]*?)"/g)) {
39+
const key = sm[1];
40+
const val = sm[2];
41+
map[`${ns}.${key}`] = val;
42+
}
43+
idx = end + 1;
44+
}
45+
// Capture very simple helper returns
46+
// func makeAddress() -> [String: Any] { return [ ... ] }
47+
for (const m of content.matchAll(/func\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(\)\s*->\s*\[[^\]]+\][^{]*\{[\s\S]*?return\s*(\[[\s\S]*?\])[\s\S]*?\}/g)) {
48+
map.__dictFuncs = map.__dictFuncs || {};
49+
map.__dictFuncs[m[1]] = { kind: 'dict', text: m[2] };
50+
}
51+
// func makeProducts() -> [[String: Any]] { return [ ... ] } (array)
52+
for (const m of content.matchAll(/func\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(\)\s*->\s*\[\[[^\]]+\]\][^{]*\{[\s\S]*?return\s*(\[[\s\S]*?\])[\s\S]*?\}/g)) {
53+
map.__dictFuncs = map.__dictFuncs || {};
54+
map.__dictFuncs[m[1]] = { kind: 'array', text: m[2] };
55+
}
56+
}
57+
} catch (_) {}
58+
return map;
59+
}
60+
61+
module.exports = { buildCrossFileConstMap };

src/analyze/swift/custom.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Custom function detection for Swift
3+
*/
4+
5+
const { normalizeChainPart, endsWithChain, extractStringLiteral, isIdentifier } = require('./utils');
6+
7+
function matchCustomSignature(call, customFunctionSignatures) {
8+
if (!Array.isArray(customFunctionSignatures) || customFunctionSignatures.length === 0) return null;
9+
const chain = Array.isArray(call.calleeChain) ? call.calleeChain.map(normalizeChainPart) : [];
10+
11+
for (const cfg of customFunctionSignatures) {
12+
if (!cfg || !cfg.functionName) continue;
13+
const sigParts = cfg.functionName.split('.').map(normalizeChainPart).filter(Boolean);
14+
if (sigParts.length === 0) continue;
15+
if (endsWithChain(chain, sigParts)) return cfg;
16+
}
17+
return null;
18+
}
19+
20+
function matchImplicitCustom(call) {
21+
const chain = Array.isArray(call.calleeChain) ? call.calleeChain.map(normalizeChainPart) : [];
22+
const last = chain[chain.length - 1] || '';
23+
if (last === 'module' || last === 'func') {
24+
return { functionName: chain.join('.'), eventIndex: 0, propertiesIndex: 1, extraParams: [] };
25+
}
26+
const name = call.name || '';
27+
if (/^customTrackFunction\d*$/.test(name)) {
28+
return { functionName: name, eventIndex: 0, propertiesIndex: 1, extraParams: [] };
29+
}
30+
if (name === 'customTrackNoProps') {
31+
return { functionName: name, eventIndex: 0, propertiesIndex: 9999, extraParams: [] };
32+
}
33+
return null;
34+
}
35+
36+
module.exports = { matchCustomSignature, matchImplicitCustom };

0 commit comments

Comments
 (0)