@hyperfixi/testing-framework 2.0.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.
- package/dist/assertions-BImuwZsB.d.mts +458 -0
- package/dist/assertions-BImuwZsB.d.ts +458 -0
- package/dist/assertions.d.mts +1 -0
- package/dist/assertions.d.ts +1 -0
- package/dist/assertions.js +625 -0
- package/dist/assertions.js.map +1 -0
- package/dist/assertions.mjs +621 -0
- package/dist/assertions.mjs.map +1 -0
- package/dist/index.d.mts +246 -0
- package/dist/index.d.ts +246 -0
- package/dist/index.js +1465 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1435 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +121 -0
- package/src/assertions.test.ts +490 -0
- package/src/assertions.ts +779 -0
- package/src/index.test.ts +490 -0
- package/src/index.ts +601 -0
- package/src/jsdom.d.ts +7 -0
- package/src/multilingual/README.md +295 -0
- package/src/multilingual/bundle-builder.ts +345 -0
- package/src/multilingual/cli.ts +224 -0
- package/src/multilingual/index.ts +68 -0
- package/src/multilingual/orchestrator.ts +275 -0
- package/src/multilingual/pattern-loader.ts +176 -0
- package/src/multilingual/reporters/console-reporter.ts +294 -0
- package/src/multilingual/reporters/json-reporter.ts +99 -0
- package/src/multilingual/reporters/regression-reporter.ts +263 -0
- package/src/multilingual/tools/analyze-failures.ts +326 -0
- package/src/multilingual/types.ts +268 -0
- package/src/multilingual/validators/parse-diagnostics.ts +337 -0
- package/src/multilingual/validators/parse-validator.ts +193 -0
- package/src/multilingual/validators/size-validator.ts +187 -0
- package/src/runner.test.ts +813 -0
- package/src/runner.ts +639 -0
- package/src/types.ts +505 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for multilingual testing framework
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supported languages
|
|
7
|
+
*/
|
|
8
|
+
export type LanguageCode =
|
|
9
|
+
| 'ar' // Arabic (VSO)
|
|
10
|
+
| 'bn' // Bengali (SOV)
|
|
11
|
+
| 'de' // German (V2)
|
|
12
|
+
| 'en' // English (SVO)
|
|
13
|
+
| 'es' // Spanish (SVO)
|
|
14
|
+
| 'fr' // French (SVO)
|
|
15
|
+
| 'hi' // Hindi (SOV)
|
|
16
|
+
| 'id' // Indonesian (SVO)
|
|
17
|
+
| 'it' // Italian (SVO)
|
|
18
|
+
| 'ja' // Japanese (SOV)
|
|
19
|
+
| 'ko' // Korean (SOV)
|
|
20
|
+
| 'ms' // Malay (SVO)
|
|
21
|
+
| 'pl' // Polish (SVO)
|
|
22
|
+
| 'pt' // Portuguese (SVO)
|
|
23
|
+
| 'qu' // Quechua (SOV)
|
|
24
|
+
| 'ru' // Russian (SVO)
|
|
25
|
+
| 'sw' // Swahili (SVO)
|
|
26
|
+
| 'th' // Thai (SVO)
|
|
27
|
+
| 'tl' // Tagalog (VSO)
|
|
28
|
+
| 'tr' // Turkish (SOV)
|
|
29
|
+
| 'uk' // Ukrainian (SVO)
|
|
30
|
+
| 'vi' // Vietnamese (SVO)
|
|
31
|
+
| 'zh'; // Chinese (SVO)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Word order types
|
|
35
|
+
*/
|
|
36
|
+
export type WordOrder = 'SVO' | 'SOV' | 'VSO' | 'V2';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Pattern from the patterns-reference database
|
|
40
|
+
*/
|
|
41
|
+
export interface Pattern {
|
|
42
|
+
id: string;
|
|
43
|
+
title: string;
|
|
44
|
+
raw_code: string;
|
|
45
|
+
description: string;
|
|
46
|
+
feature: string;
|
|
47
|
+
source_url?: string;
|
|
48
|
+
created_at: Date;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Pattern translation
|
|
53
|
+
*/
|
|
54
|
+
export interface PatternTranslation {
|
|
55
|
+
codeExampleId: string;
|
|
56
|
+
language: LanguageCode;
|
|
57
|
+
hyperscript: string;
|
|
58
|
+
wordOrder: WordOrder;
|
|
59
|
+
confidence: number;
|
|
60
|
+
verifiedParses: boolean;
|
|
61
|
+
roleAlignmentScore: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Test configuration
|
|
66
|
+
*/
|
|
67
|
+
export interface TestConfig {
|
|
68
|
+
/** Languages to test (undefined = all) */
|
|
69
|
+
languages?: LanguageCode[];
|
|
70
|
+
|
|
71
|
+
/** Bundle to use (if undefined, will build/select automatically) */
|
|
72
|
+
bundle?: string;
|
|
73
|
+
|
|
74
|
+
/** Whether to build bundle before testing */
|
|
75
|
+
build?: boolean;
|
|
76
|
+
|
|
77
|
+
/** Test mode */
|
|
78
|
+
mode: 'quick' | 'full';
|
|
79
|
+
|
|
80
|
+
/** Enable verbose logging */
|
|
81
|
+
verbose?: boolean;
|
|
82
|
+
|
|
83
|
+
/** Enable regression comparison */
|
|
84
|
+
regression?: boolean;
|
|
85
|
+
|
|
86
|
+
/** Minimum confidence threshold for semantic parsing */
|
|
87
|
+
confidenceThreshold?: number;
|
|
88
|
+
|
|
89
|
+
/** Only test patterns that have verifiedParses = true */
|
|
90
|
+
verifiedOnly?: boolean;
|
|
91
|
+
|
|
92
|
+
/** Pattern categories to test */
|
|
93
|
+
categories?: string[];
|
|
94
|
+
|
|
95
|
+
/** Number of patterns per language in quick mode */
|
|
96
|
+
quickModeLimit?: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Parse validation result
|
|
101
|
+
*/
|
|
102
|
+
export interface ParseResult {
|
|
103
|
+
pattern: PatternTranslation;
|
|
104
|
+
success: boolean;
|
|
105
|
+
command?: string;
|
|
106
|
+
roles?: Record<string, unknown>;
|
|
107
|
+
confidence?: number;
|
|
108
|
+
parser?: 'semantic' | 'traditional';
|
|
109
|
+
error?: string;
|
|
110
|
+
duration: number; // ms
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Size validation result
|
|
115
|
+
*/
|
|
116
|
+
export interface SizeResult {
|
|
117
|
+
bundlePath: string;
|
|
118
|
+
size: number; // bytes
|
|
119
|
+
gzipSize: number | undefined; // bytes
|
|
120
|
+
exceedsThreshold: boolean;
|
|
121
|
+
threshold: number | undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Language test results
|
|
126
|
+
*/
|
|
127
|
+
export interface LanguageResults {
|
|
128
|
+
language: LanguageCode;
|
|
129
|
+
bundle: string;
|
|
130
|
+
bundleSize?: number;
|
|
131
|
+
|
|
132
|
+
/** Parse validation results */
|
|
133
|
+
parseResults: ParseResult[];
|
|
134
|
+
parseSuccess: number;
|
|
135
|
+
parseFailure: number;
|
|
136
|
+
parseRate: number;
|
|
137
|
+
avgConfidence: number;
|
|
138
|
+
|
|
139
|
+
/** Duration in ms */
|
|
140
|
+
duration: number;
|
|
141
|
+
|
|
142
|
+
/** Overall status */
|
|
143
|
+
status: 'pass' | 'fail' | 'warning';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Complete test run results
|
|
148
|
+
*/
|
|
149
|
+
export interface TestResults {
|
|
150
|
+
timestamp: string;
|
|
151
|
+
commit: string | undefined;
|
|
152
|
+
config: TestConfig;
|
|
153
|
+
|
|
154
|
+
/** Results by language */
|
|
155
|
+
languageResults: LanguageResults[];
|
|
156
|
+
|
|
157
|
+
/** Bundle size information */
|
|
158
|
+
bundles: Record<
|
|
159
|
+
string,
|
|
160
|
+
{
|
|
161
|
+
size: number;
|
|
162
|
+
languages: LanguageCode[];
|
|
163
|
+
gzipSize?: number;
|
|
164
|
+
}
|
|
165
|
+
>;
|
|
166
|
+
|
|
167
|
+
/** Summary statistics */
|
|
168
|
+
summary: {
|
|
169
|
+
totalPatterns: number;
|
|
170
|
+
totalSuccess: number;
|
|
171
|
+
totalFailure: number;
|
|
172
|
+
totalDuration: number;
|
|
173
|
+
overallStatus: 'pass' | 'fail' | 'warning';
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Baseline data for regression testing
|
|
179
|
+
*/
|
|
180
|
+
export interface Baseline {
|
|
181
|
+
timestamp: string;
|
|
182
|
+
commit: string;
|
|
183
|
+
languages: Partial<
|
|
184
|
+
Record<
|
|
185
|
+
LanguageCode,
|
|
186
|
+
{
|
|
187
|
+
parseSuccess: number;
|
|
188
|
+
parseFailure: number;
|
|
189
|
+
parseRate: number;
|
|
190
|
+
avgConfidence: number;
|
|
191
|
+
bundleSize: number | undefined;
|
|
192
|
+
/** Pattern-level results for detailed tracking */
|
|
193
|
+
patterns: Record<string, { success: boolean; confidence: number | undefined }> | undefined;
|
|
194
|
+
}
|
|
195
|
+
>
|
|
196
|
+
>;
|
|
197
|
+
bundles: Record<
|
|
198
|
+
string,
|
|
199
|
+
{
|
|
200
|
+
size: number;
|
|
201
|
+
languages: LanguageCode[];
|
|
202
|
+
gzipSize: number | undefined;
|
|
203
|
+
}
|
|
204
|
+
>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Regression comparison result
|
|
209
|
+
*/
|
|
210
|
+
export interface RegressionResult {
|
|
211
|
+
language: LanguageCode;
|
|
212
|
+
parseRateDelta: number; // % change
|
|
213
|
+
avgConfidenceDelta: number; // absolute change
|
|
214
|
+
bundleSizeDelta: number | undefined; // % change
|
|
215
|
+
newFailures: string[]; // pattern IDs
|
|
216
|
+
newSuccesses: string[]; // pattern IDs
|
|
217
|
+
status: 'improved' | 'regressed' | 'unchanged';
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Bundle build options
|
|
222
|
+
*/
|
|
223
|
+
export interface BundleBuildOptions {
|
|
224
|
+
languages: LanguageCode[];
|
|
225
|
+
outputPath: string | undefined;
|
|
226
|
+
groupName: string | undefined; // e.g., 'western', 'east-asian'
|
|
227
|
+
updateConfig: boolean | undefined; // Update tsup.config.ts
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Bundle information
|
|
232
|
+
*/
|
|
233
|
+
export interface BundleInfo {
|
|
234
|
+
name: string;
|
|
235
|
+
path: string;
|
|
236
|
+
languages: LanguageCode[];
|
|
237
|
+
size: number;
|
|
238
|
+
exists: boolean;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Reporter interface
|
|
243
|
+
*/
|
|
244
|
+
export interface Reporter {
|
|
245
|
+
reportStart(config: TestConfig): void;
|
|
246
|
+
reportLanguageStart(language: LanguageCode, bundle: string): void;
|
|
247
|
+
reportLanguageComplete(results: LanguageResults): void;
|
|
248
|
+
reportComplete(results: TestResults): void;
|
|
249
|
+
reportRegression?(results: RegressionResult[]): void;
|
|
250
|
+
reportError(error: Error): void;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Validator interface
|
|
255
|
+
*/
|
|
256
|
+
export interface Validator<T> {
|
|
257
|
+
validate(input: unknown): Promise<T>;
|
|
258
|
+
getName(): string;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Sampling strategy for pattern selection
|
|
263
|
+
*/
|
|
264
|
+
export type SamplingStrategy =
|
|
265
|
+
| { type: 'all' }
|
|
266
|
+
| { type: 'first'; count: number }
|
|
267
|
+
| { type: 'random'; count: number }
|
|
268
|
+
| { type: 'stratified'; perCategory: number };
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse Diagnostics - Enhanced debugging for multilingual parsing failures
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { PatternTranslation, LanguageCode, ParseResult } from '../types';
|
|
6
|
+
|
|
7
|
+
export interface ParseTrace {
|
|
8
|
+
stage: string;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
data: unknown;
|
|
11
|
+
error: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DiagnosticResult {
|
|
15
|
+
pattern: PatternTranslation;
|
|
16
|
+
traces: ParseTrace[];
|
|
17
|
+
parseResult: ParseResult | undefined;
|
|
18
|
+
analysisNotes: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface FailurePattern {
|
|
22
|
+
type: string;
|
|
23
|
+
count: number;
|
|
24
|
+
examples: string[];
|
|
25
|
+
affectedLanguages: LanguageCode[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Parse Diagnostics Collector
|
|
30
|
+
*
|
|
31
|
+
* Captures detailed trace information during parsing for debugging
|
|
32
|
+
*/
|
|
33
|
+
export class ParseDiagnostics {
|
|
34
|
+
private traces: Map<string, ParseTrace[]> = new Map();
|
|
35
|
+
private enabled: boolean;
|
|
36
|
+
|
|
37
|
+
constructor(enabled: boolean = false) {
|
|
38
|
+
this.enabled = enabled;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Enable/disable diagnostics collection
|
|
43
|
+
*/
|
|
44
|
+
setEnabled(enabled: boolean): void {
|
|
45
|
+
this.enabled = enabled;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Record a trace event
|
|
50
|
+
*/
|
|
51
|
+
trace(patternId: string, stage: string, data?: unknown, error?: string): void {
|
|
52
|
+
if (!this.enabled) return;
|
|
53
|
+
|
|
54
|
+
const traces = this.traces.get(patternId) || [];
|
|
55
|
+
traces.push({
|
|
56
|
+
stage,
|
|
57
|
+
timestamp: performance.now(),
|
|
58
|
+
data,
|
|
59
|
+
error,
|
|
60
|
+
});
|
|
61
|
+
this.traces.set(patternId, traces);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get traces for a pattern
|
|
66
|
+
*/
|
|
67
|
+
getTraces(patternId: string): ParseTrace[] {
|
|
68
|
+
return this.traces.get(patternId) || [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Clear all traces
|
|
73
|
+
*/
|
|
74
|
+
clear(): void {
|
|
75
|
+
this.traces.clear();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Export all traces
|
|
80
|
+
*/
|
|
81
|
+
exportTraces(): Map<string, ParseTrace[]> {
|
|
82
|
+
return new Map(this.traces);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Failure Pattern Analyzer
|
|
88
|
+
*
|
|
89
|
+
* Analyzes parse failures to identify common patterns and issues
|
|
90
|
+
*/
|
|
91
|
+
export class FailureAnalyzer {
|
|
92
|
+
/**
|
|
93
|
+
* Analyze failures and group by common patterns
|
|
94
|
+
*/
|
|
95
|
+
analyzeFailures(results: ParseResult[]): FailurePattern[] {
|
|
96
|
+
const failures = results.filter(r => !r.success);
|
|
97
|
+
const patterns: Map<string, FailurePattern> = new Map();
|
|
98
|
+
|
|
99
|
+
for (const failure of failures) {
|
|
100
|
+
// Categorize by error message
|
|
101
|
+
const errorType = this.categorizeError(failure.error || 'Unknown error');
|
|
102
|
+
|
|
103
|
+
if (!patterns.has(errorType)) {
|
|
104
|
+
patterns.set(errorType, {
|
|
105
|
+
type: errorType,
|
|
106
|
+
count: 0,
|
|
107
|
+
examples: [],
|
|
108
|
+
affectedLanguages: [],
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const pattern = patterns.get(errorType)!;
|
|
113
|
+
pattern.count++;
|
|
114
|
+
|
|
115
|
+
if (pattern.examples.length < 5) {
|
|
116
|
+
pattern.examples.push(failure.pattern.hyperscript);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!pattern.affectedLanguages.includes(failure.pattern.language)) {
|
|
120
|
+
pattern.affectedLanguages.push(failure.pattern.language);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return Array.from(patterns.values()).sort((a, b) => b.count - a.count);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Categorize error by type
|
|
129
|
+
*/
|
|
130
|
+
private categorizeError(error: string): string {
|
|
131
|
+
if (error.includes('null or undefined')) {
|
|
132
|
+
return 'Parse returned null';
|
|
133
|
+
}
|
|
134
|
+
if (error.includes('timeout')) {
|
|
135
|
+
return 'Parse timeout';
|
|
136
|
+
}
|
|
137
|
+
if (error.includes('token')) {
|
|
138
|
+
return 'Tokenization error';
|
|
139
|
+
}
|
|
140
|
+
if (error.includes('syntax')) {
|
|
141
|
+
return 'Syntax error';
|
|
142
|
+
}
|
|
143
|
+
if (error.includes('semantic')) {
|
|
144
|
+
return 'Semantic error';
|
|
145
|
+
}
|
|
146
|
+
return 'Other error';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Analyze language-specific issues
|
|
151
|
+
*/
|
|
152
|
+
analyzeByLanguage(results: ParseResult[]): Record<
|
|
153
|
+
LanguageCode,
|
|
154
|
+
{
|
|
155
|
+
totalPatterns: number;
|
|
156
|
+
failures: number;
|
|
157
|
+
commonErrors: string[];
|
|
158
|
+
problematicPatterns: string[];
|
|
159
|
+
}
|
|
160
|
+
> {
|
|
161
|
+
const byLanguage: Record<string, any> = {};
|
|
162
|
+
|
|
163
|
+
for (const result of results) {
|
|
164
|
+
const lang = result.pattern.language;
|
|
165
|
+
|
|
166
|
+
if (!byLanguage[lang]) {
|
|
167
|
+
byLanguage[lang] = {
|
|
168
|
+
totalPatterns: 0,
|
|
169
|
+
failures: 0,
|
|
170
|
+
commonErrors: [] as string[],
|
|
171
|
+
problematicPatterns: [] as string[],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
byLanguage[lang].totalPatterns++;
|
|
176
|
+
|
|
177
|
+
if (!result.success) {
|
|
178
|
+
byLanguage[lang].failures++;
|
|
179
|
+
|
|
180
|
+
const error = result.error || 'Unknown';
|
|
181
|
+
if (!byLanguage[lang].commonErrors.includes(error)) {
|
|
182
|
+
byLanguage[lang].commonErrors.push(error);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (byLanguage[lang].problematicPatterns.length < 10) {
|
|
186
|
+
byLanguage[lang].problematicPatterns.push(result.pattern.hyperscript);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return byLanguage as Record<LanguageCode, any>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Identify patterns in failed hyperscript
|
|
196
|
+
*/
|
|
197
|
+
identifyFailurePatterns(failures: ParseResult[]): {
|
|
198
|
+
multiClause: number;
|
|
199
|
+
eventModifiers: number;
|
|
200
|
+
styleProperties: number;
|
|
201
|
+
conditionals: number;
|
|
202
|
+
windowEvents: number;
|
|
203
|
+
complexSelectors: number;
|
|
204
|
+
} {
|
|
205
|
+
const patterns = {
|
|
206
|
+
multiClause: 0,
|
|
207
|
+
eventModifiers: 0,
|
|
208
|
+
styleProperties: 0,
|
|
209
|
+
conditionals: 0,
|
|
210
|
+
windowEvents: 0,
|
|
211
|
+
complexSelectors: 0,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
for (const failure of failures) {
|
|
215
|
+
const code = failure.pattern.hyperscript;
|
|
216
|
+
|
|
217
|
+
// Multi-clause (それから, ثم, then)
|
|
218
|
+
if (
|
|
219
|
+
code.includes('それから') ||
|
|
220
|
+
code.includes('ثم') ||
|
|
221
|
+
code.includes('then') ||
|
|
222
|
+
code.includes('그러면') ||
|
|
223
|
+
code.includes('그리고')
|
|
224
|
+
) {
|
|
225
|
+
patterns.multiClause++;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Event modifiers
|
|
229
|
+
if (code.includes('[') || code.includes('debounced') || code.includes('throttled')) {
|
|
230
|
+
patterns.eventModifiers++;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Style properties (*background, *opacity, etc.)
|
|
234
|
+
if (code.includes('*')) {
|
|
235
|
+
patterns.styleProperties++;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Conditionals (if, もし, إذا, etc.)
|
|
239
|
+
if (
|
|
240
|
+
code.includes('if ') ||
|
|
241
|
+
code.includes('もし') ||
|
|
242
|
+
code.includes('إذا') ||
|
|
243
|
+
code.includes('一致する') ||
|
|
244
|
+
code.includes('match')
|
|
245
|
+
) {
|
|
246
|
+
patterns.conditionals++;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Window events
|
|
250
|
+
if (
|
|
251
|
+
code.includes('ウィンドウ') ||
|
|
252
|
+
code.includes('window') ||
|
|
253
|
+
code.includes('النافذة') ||
|
|
254
|
+
code.includes('창')
|
|
255
|
+
) {
|
|
256
|
+
patterns.windowEvents++;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Complex selectors
|
|
260
|
+
if (
|
|
261
|
+
code.includes('closest') ||
|
|
262
|
+
code.includes('最も近い') ||
|
|
263
|
+
code.includes('<') ||
|
|
264
|
+
code.includes('first') ||
|
|
265
|
+
code.includes('最初')
|
|
266
|
+
) {
|
|
267
|
+
patterns.complexSelectors++;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return patterns;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Generate diagnostic report
|
|
276
|
+
*/
|
|
277
|
+
generateReport(results: ParseResult[]): string {
|
|
278
|
+
const failures = results.filter(r => !r.success);
|
|
279
|
+
const failurePatterns = this.analyzeFailures(results);
|
|
280
|
+
const byLanguage = this.analyzeByLanguage(results);
|
|
281
|
+
const codePatterns = this.identifyFailurePatterns(failures);
|
|
282
|
+
|
|
283
|
+
let report = '# Parse Failure Analysis Report\n\n';
|
|
284
|
+
|
|
285
|
+
report += `## Summary\n`;
|
|
286
|
+
report += `- Total patterns: ${results.length}\n`;
|
|
287
|
+
report += `- Failures: ${failures.length} (${((failures.length / results.length) * 100).toFixed(1)}%)\n`;
|
|
288
|
+
report += `- Success rate: ${(((results.length - failures.length) / results.length) * 100).toFixed(1)}%\n\n`;
|
|
289
|
+
|
|
290
|
+
report += `## Common Failure Types\n\n`;
|
|
291
|
+
for (const pattern of failurePatterns.slice(0, 5)) {
|
|
292
|
+
report += `### ${pattern.type} (${pattern.count} occurrences)\n`;
|
|
293
|
+
report += `- Affected languages: ${pattern.affectedLanguages.join(', ')}\n`;
|
|
294
|
+
report += `- Examples:\n`;
|
|
295
|
+
pattern.examples.forEach(ex => {
|
|
296
|
+
report += ` - "${ex}"\n`;
|
|
297
|
+
});
|
|
298
|
+
report += '\n';
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
report += `## Failure Patterns in Code\n\n`;
|
|
302
|
+
report += `- Multi-clause patterns: ${codePatterns.multiClause}\n`;
|
|
303
|
+
report += `- Event modifiers: ${codePatterns.eventModifiers}\n`;
|
|
304
|
+
report += `- Style properties: ${codePatterns.styleProperties}\n`;
|
|
305
|
+
report += `- Conditionals: ${codePatterns.conditionals}\n`;
|
|
306
|
+
report += `- Window events: ${codePatterns.windowEvents}\n`;
|
|
307
|
+
report += `- Complex selectors: ${codePatterns.complexSelectors}\n\n`;
|
|
308
|
+
|
|
309
|
+
report += `## By Language\n\n`;
|
|
310
|
+
const sortedLangs = Object.entries(byLanguage).sort(([, a], [, b]) => b.failures - a.failures);
|
|
311
|
+
|
|
312
|
+
for (const [lang, data] of sortedLangs.slice(0, 10)) {
|
|
313
|
+
const failRate = ((data.failures / data.totalPatterns) * 100).toFixed(1);
|
|
314
|
+
report += `### ${lang.toUpperCase()} - ${data.failures}/${data.totalPatterns} failures (${failRate}%)\n`;
|
|
315
|
+
report += `Common errors:\n`;
|
|
316
|
+
data.commonErrors.slice(0, 3).forEach((err: string) => {
|
|
317
|
+
report += `- ${err}\n`;
|
|
318
|
+
});
|
|
319
|
+
report += '\n';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return report;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Create a diagnostic session
|
|
328
|
+
*/
|
|
329
|
+
export function createDiagnosticSession(enabled: boolean = true): {
|
|
330
|
+
diagnostics: ParseDiagnostics;
|
|
331
|
+
analyzer: FailureAnalyzer;
|
|
332
|
+
} {
|
|
333
|
+
return {
|
|
334
|
+
diagnostics: new ParseDiagnostics(enabled),
|
|
335
|
+
analyzer: new FailureAnalyzer(),
|
|
336
|
+
};
|
|
337
|
+
}
|