pumuki-ast-hooks 5.3.29 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,8 @@
1
1
 
2
2
  const path = require('path');
3
3
  const glob = require('glob');
4
+ const { execSync } = require('child_process');
5
+ const env = require('../../config/env');
4
6
  const { pushFinding, mapToLevel, SyntaxKind, isTestFile, platformOf, getRepoRoot } = require(path.join(__dirname, '../ast-core'));
5
7
  const { iOSEnterpriseAnalyzer } = require(path.join(__dirname, 'analyzers/iOSEnterpriseAnalyzer'));
6
8
  const { iOSArchitectureDetector } = require(path.join(__dirname, 'analyzers/iOSArchitectureDetector'));
@@ -27,14 +29,40 @@ async function runIOSIntelligence(project, findings, platform) {
27
29
  console.error(`[iOS AST Intelligence] Running SourceKitten-based analysis...`);
28
30
  const astAnalyzer = new iOSASTIntelligentAnalyzer(findings);
29
31
  const root = getRepoRoot();
30
- const swiftFilesForAST = glob.sync('**/*.swift', {
31
- cwd: root,
32
- ignore: ['**/node_modules/**', '**/build/**', '**/Pods/**', '**/.build/**', '**/CustomLintRules/**'],
33
- absolute: true,
34
- });
32
+ const stagingOnly = env.get('STAGING_ONLY_MODE', '0') === '1';
33
+ let stagedRelSwift = [];
34
+ if (stagingOnly) {
35
+ try {
36
+ stagedRelSwift = execSync('git diff --cached --name-only --diff-filter=ACM', {
37
+ encoding: 'utf8',
38
+ cwd: root,
39
+ stdio: ['ignore', 'pipe', 'pipe']
40
+ })
41
+ .trim()
42
+ .split('\n')
43
+ .map(s => s.trim())
44
+ .filter(Boolean)
45
+ .filter(p => p.endsWith('.swift'));
46
+ } catch {
47
+ stagedRelSwift = [];
48
+ }
49
+ }
50
+
51
+ const swiftFilesForAST = stagingOnly
52
+ ? stagedRelSwift.map(rel => path.join(root, rel))
53
+ : glob.sync('**/*.swift', {
54
+ cwd: root,
55
+ ignore: ['**/node_modules/**', '**/build/**', '**/Pods/**', '**/.build/**', '**/CustomLintRules/**'],
56
+ absolute: true,
57
+ });
35
58
 
36
59
  for (const swiftFile of swiftFilesForAST) {
37
- astAnalyzer.analyzeFile(swiftFile);
60
+ const rel = stagingOnly ? path.relative(root, swiftFile).replace(/\\/g, '/') : null;
61
+ astAnalyzer.analyzeFile(swiftFile, {
62
+ repoRoot: root,
63
+ displayPath: swiftFile,
64
+ stagedRelPath: stagingOnly ? rel : null
65
+ });
38
66
  }
39
67
 
40
68
  astAnalyzer.finalizeGodClassDetection();
@@ -42,6 +70,10 @@ async function runIOSIntelligence(project, findings, platform) {
42
70
 
43
71
  await runSwiftLintNative(findings);
44
72
 
73
+ if (stagingOnly) {
74
+ return;
75
+ }
76
+
45
77
  project.getSourceFiles().forEach((sf) => {
46
78
  if (!sf || typeof sf.getFilePath !== 'function') return;
47
79
  const filePath = sf.getFilePath();
@@ -87,11 +119,13 @@ async function runIOSIntelligence(project, findings, platform) {
87
119
 
88
120
  try {
89
121
  const root = getRepoRoot();
90
- const swiftFiles = glob.sync('**/*.swift', {
91
- cwd: root,
92
- ignore: ['**/node_modules/**', '**/build/**', '**/Pods/**', '**/.build/**'],
93
- absolute: true,
94
- });
122
+ const swiftFiles = stagingOnly
123
+ ? stagedRelSwift.map(rel => path.join(root, rel))
124
+ : glob.sync('**/*.swift', {
125
+ cwd: root,
126
+ ignore: ['**/node_modules/**', '**/build/**', '**/Pods/**', '**/.build/**'],
127
+ absolute: true,
128
+ });
95
129
 
96
130
  if (swiftFiles.length > 0) {
97
131
  console.error(`[iOS Enterprise] Analyzing ${swiftFiles.length} Swift files with SourceKitten...`);
@@ -2,12 +2,32 @@ const { execSync } = require('child_process');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
4
  const { pushFileFinding } = require('../ast-core');
5
+ const env = require('../../config/env');
6
+
7
+ function getStagedSwiftFiles(repoRoot) {
8
+ try {
9
+ return execSync('git diff --cached --name-only --diff-filter=ACM', {
10
+ encoding: 'utf8',
11
+ cwd: repoRoot,
12
+ stdio: ['ignore', 'pipe', 'pipe']
13
+ })
14
+ .trim()
15
+ .split('\n')
16
+ .map(s => s.trim())
17
+ .filter(Boolean)
18
+ .filter(p => p.endsWith('.swift'));
19
+ } catch {
20
+ return [];
21
+ }
22
+ }
5
23
 
6
24
  async function runSwiftLintNative(findings) {
7
25
  try {
8
26
  const { getRepoRoot } = require('../ast-core');
9
27
  const projectRoot = getRepoRoot();
10
28
  const customRulesPath = path.join(projectRoot, 'CustomLintRules');
29
+ const stagingOnly = env.get('STAGING_ONLY_MODE', '0') === '1';
30
+ const stagedSwiftRel = stagingOnly ? getStagedSwiftFiles(projectRoot) : null;
11
31
 
12
32
  if (!fs.existsSync(customRulesPath)) {
13
33
  console.log('[SwiftLint Native] CustomLintRules package not found - skipping');
@@ -35,7 +55,10 @@ async function runSwiftLintNative(findings) {
35
55
  timeout: 60000
36
56
  });
37
57
 
38
- parseSwiftLintOutput(result, findings);
58
+ parseSwiftLintOutput(result, findings, {
59
+ repoRoot: projectRoot,
60
+ stagedSwiftRel
61
+ });
39
62
 
40
63
  console.log('[SwiftLint Native] ✅ Custom rules executed');
41
64
 
@@ -44,7 +67,13 @@ async function runSwiftLintNative(findings) {
44
67
  }
45
68
  }
46
69
 
47
- function parseSwiftLintOutput(output, findings) {
70
+ function parseSwiftLintOutput(output, findings, options = {}) {
71
+ const { repoRoot, stagedSwiftRel } = options;
72
+ const stagingOnly = Array.isArray(stagedSwiftRel);
73
+ const stagedAbs = stagingOnly && repoRoot
74
+ ? new Set(stagedSwiftRel.map(rel => path.join(repoRoot, rel)))
75
+ : null;
76
+
48
77
  const lines = output.split('\n');
49
78
 
50
79
  for (const line of lines) {
@@ -53,6 +82,14 @@ function parseSwiftLintOutput(output, findings) {
53
82
  if (match) {
54
83
  const [, filePath, lineNum, col, severity, message] = match;
55
84
 
85
+ if (stagingOnly && stagedAbs) {
86
+ const normalized = String(filePath || '');
87
+ const isStaged = stagedAbs.has(normalized) || Array.from(stagedAbs).some(p => normalized.endsWith(p));
88
+ if (!isStaged) {
89
+ continue;
90
+ }
91
+ }
92
+
56
93
  const level = severity === 'error' ? 'high' : 'medium';
57
94
  const ruleId = extractRuleId(message);
58
95
 
@@ -1,8 +0,0 @@
1
- {
2
- "notification": {
3
- "enabled": true
4
- },
5
- "recovery": {
6
- "maxAttempts": 5
7
- }
8
- }