From 8a05f297245a9a1cc531dc454a1870654230b305 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Wed, 13 May 2026 04:18:28 +0000 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20Phase=206=20cutover=20=E2=80=94=20d?= =?UTF-8?q?elete=20Java=20reference,=20ship=20v1.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is the destructive cutover finalizing the Java→Go port. ~133k lines deleted, ~720 added (docs + security.yml retarget). ## Deleted - `src/` (Java + frontend + test trees: ~640 files, ~133k LoC) - `pom.xml`, `spotbugs-exclude.xml` (Maven + SpotBugs config) - `.github/workflows/ci-java.yml` — Java compile + unit-test gate - `.github/workflows/release-java.yml` — Java release flow - `.github/workflows/beta-java.yml` — Java beta release flow - `.github/workflows/go-parity.yml` — Java↔Go parity test (Java jar build that fed it is gone) ## Updated - `.gitignore` — stripped Java/Maven/frontend patterns, kept Go + cross-cutting (env, secrets, OS, IDE, codeiq runtime artifacts). - `.github/workflows/security.yml` — OSV-Scanner now reads `go/go.mod`; Semgrep swapped `p/java` → `p/golang`; jscpd retargeted to `go/cmd go/internal` with Go-tuned ignore patterns. - `README.md` — Go-native rewrite: install via pre-built binary or Homebrew tap, Cosign verify recipe, CLI reference for the Go command set, MCP integration snippet for `.mcp.json`. - `CLAUDE.md` — full rewrite (43 KB → ~16 KB). Go module layout, detector authoring contract (with detectors_register.go choke-point warning), Kuzu v0.7.1 quirks, MCP SDK v1.6 API shape, RE2-vs-Java regex gotchas, perf war stories. - `PROJECT_SUMMARY.md` — refreshed for Go-only entrypoints + directory map; updated `Where to look next` links. - `CHANGELOG.md` — added `[v1.0.0] - 2026-05-13` entry summarizing Phase 1-5 surface + Phase 6 removal. ## Migration notes for anyone needing Java history The pre-cutover Java state is preserved on `origin/main` at commit `c363727` (the squash-merge that landed the Go port). Recovery: git show c363727:src/main/java/ # one file git checkout c363727 -- src/main/java/ # restore files ## Test plan - [x] `cd go && CGO_ENABLED=1 go test ./... -count=1` → 828 pass - [x] yaml-lint on the modified workflow + the goreleaser config - [x] `git status --short` clean after stage - [ ] CI green on the cutover PR (go-ci, perf-gate, security, CodeQL, Scorecard, Socket) - [ ] After merge: `git tag -s v1.0.0` triggers release-go.yml and produces a draft GitHub Release with multi-arch archives + SBOMs + Cosign-signed checksums. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/beta-java.yml | 72 - .github/workflows/ci-java.yml | 54 - .github/workflows/go-parity.yml | 101 - .github/workflows/release-java.yml | 106 - .github/workflows/security.yml | 96 +- .gitignore | 64 +- CHANGELOG.md | 43 + CLAUDE.md | 806 ++-- PROJECT_SUMMARY.md | 236 +- README.md | 392 +- pom.xml | 643 --- spotbugs-exclude.xml | 93 - src/assembly/source-bundle.xml | 58 - src/main/antlr4/imports/UnicodeClasses.g4 | 1656 ------- .../iq/grammar/cpp/CPP14Lexer.g4 | 398 -- .../iq/grammar/cpp/CPP14Parser.g4 | 1076 ----- .../iq/grammar/csharp/CSharpLexer.g4 | 1059 ----- .../iq/grammar/csharp/CSharpParser.g4 | 1325 ------ .../csharp/CSharpPreprocessorParser.g4 | 48 - .../iq/grammar/golang/GoLexer.g4 | 223 - .../iq/grammar/golang/GoParser.g4 | 541 --- .../iq/grammar/javascript/JavaScriptLexer.g4 | 285 -- .../iq/grammar/javascript/JavaScriptParser.g4 | 584 --- .../iq/grammar/kotlin/KotlinLexer.g4 | 450 -- .../iq/grammar/kotlin/KotlinParser.g4 | 893 ---- .../iq/grammar/kotlin/UnicodeClasses.g4 | 1656 ------- .../iq/grammar/python/Python3Lexer.g4 | 313 -- .../iq/grammar/python/Python3Parser.g4 | 694 --- .../iq/grammar/rust/RustLexer.g4 | 270 -- .../iq/grammar/rust/RustParser.g4 | 1198 ------ .../randomcodespace/iq/grammar/scala/Scala.g4 | 1383 ------ .../iq/grammar/typescript/TypeScriptLexer.g4 | 315 -- .../iq/grammar/typescript/TypeScriptParser.g4 | 984 ----- src/main/frontend/.gitignore | 4 - src/main/frontend/index.html | 14 - src/main/frontend/package-lock.json | 2077 --------- src/main/frontend/package.json | 35 - ...d6e968bcc3e3f9fb8eaecdf7ea2f3d2ab41deb.png | Bin 72307 -> 0 bytes ...e22f62153becae158a32a0ef8aa8037da1508.webm | Bin 158252 -> 0 bytes ...c72b585fa3d6ad6b85b44878d2427a335bdf9de.md | 432 -- ...2072c8aa5cd97f91093ec8cad3e5f7b48b55c66.md | 222 - ...d00512fbfc05f51c50987f6e805c0156f31b2d.png | Bin 13387 -> 0 bytes ...b10ff67df8fe6b39c93a7519699a0d4e67b55.webm | Bin 234633 -> 0 bytes .../frontend/playwright-report/index.html | 90 - src/main/frontend/playwright.config.ts | 104 - src/main/frontend/public/favicon.svg | 4 - src/main/frontend/src/App.tsx | 14 - .../frontend/src/components/AppLayout.tsx | 88 - src/main/frontend/src/components/Icons.tsx | 27 - .../frontend/src/context/ThemeContext.tsx | 24 - src/main/frontend/src/env.d.ts | 1 - src/main/frontend/src/hooks/useApi.ts | 42 - src/main/frontend/src/index.css | 134 - src/main/frontend/src/lib/api.ts | 114 - src/main/frontend/src/lib/mcp-tools.ts | 333 -- src/main/frontend/src/main.tsx | 19 - src/main/frontend/src/pages/Dashboard.tsx | 485 --- src/main/frontend/src/types/api.ts | 156 - src/main/frontend/test-results/.last-run.json | 4 - .../frontend/tests/e2e/accessibility.spec.ts | 210 - .../frontend/tests/e2e/edge-cases.spec.ts | 240 -- src/main/frontend/tests/e2e/file-tree.spec.ts | 260 -- src/main/frontend/tests/e2e/graph.spec.ts | 217 - .../frontend/tests/e2e/mcp-console.spec.ts | 221 - .../frontend/tests/e2e/navigation.spec.ts | 196 - .../frontend/tests/e2e/performance.spec.ts | 143 - .../frontend/tests/e2e/responsive.spec.ts | 175 - src/main/frontend/tests/e2e/search.spec.ts | 193 - src/main/frontend/tests/utils/test-helpers.ts | 227 - src/main/frontend/tsconfig.json | 25 - src/main/frontend/tsconfig.test.json | 11 - src/main/frontend/vite.config.ts | 33 - .../randomcodespace/iq/CodeIqApplication.java | 168 - .../iq/analyzer/AnalysisResult.java | 44 - .../randomcodespace/iq/analyzer/Analyzer.java | 1844 -------- .../analyzer/ArchitectureKeywordFilter.java | 129 - .../iq/analyzer/ConfigScanner.java | 543 --- .../iq/analyzer/DiscoveredFile.java | 16 - .../iq/analyzer/FileClassifier.java | 139 - .../iq/analyzer/FileDiscovery.java | 251 -- .../iq/analyzer/GraphBuilder.java | 227 - .../iq/analyzer/InfraEndpoint.java | 40 - .../iq/analyzer/InfrastructureRegistry.java | 90 - .../iq/analyzer/LayerClassifier.java | 180 - .../iq/analyzer/ServiceDetector.java | 589 --- .../iq/analyzer/StructuredParser.java | 203 - .../iq/analyzer/linker/EntityLinker.java | 100 - .../iq/analyzer/linker/GuardLinker.java | 92 - .../iq/analyzer/linker/LinkResult.java | 23 - .../iq/analyzer/linker/Linker.java | 23 - .../linker/ModuleContainmentLinker.java | 98 - .../iq/analyzer/linker/TopicLinker.java | 116 - .../iq/api/FlowController.java | 139 - .../iq/api/GlobalExceptionHandler.java | 71 - .../iq/api/GraphController.java | 395 -- .../iq/api/IntelligenceController.java | 158 - .../iq/api/SafeFileReader.java | 77 - .../iq/api/TopologyController.java | 106 - .../iq/cache/AnalysisCache.java | 960 ----- .../randomcodespace/iq/cache/FileHasher.java | 57 - .../iq/cli/AnalyzeCommand.java | 113 - .../randomcodespace/iq/cli/BundleCommand.java | 553 --- .../randomcodespace/iq/cli/CacheCommand.java | 132 - .../randomcodespace/iq/cli/CliOutput.java | 176 - .../randomcodespace/iq/cli/CodeIqCli.java | 42 - .../randomcodespace/iq/cli/ConfigCommand.java | 34 - .../iq/cli/ConfigExplainSubcommand.java | 152 - .../iq/cli/ConfigValidateSubcommand.java | 104 - .../randomcodespace/iq/cli/CypherCommand.java | 42 - .../randomcodespace/iq/cli/EnrichCommand.java | 558 --- .../randomcodespace/iq/cli/FindCommand.java | 124 - .../randomcodespace/iq/cli/FlowCommand.java | 130 - .../randomcodespace/iq/cli/GraphCommand.java | 197 - .../randomcodespace/iq/cli/IndexCommand.java | 143 - .../iq/cli/PluginsCommand.java | 577 --- .../randomcodespace/iq/cli/QueryCommand.java | 163 - .../randomcodespace/iq/cli/ServeCommand.java | 151 - .../randomcodespace/iq/cli/StatsCommand.java | 413 -- .../iq/cli/TopologyCommand.java | 167 - .../iq/cli/VersionCommand.java | 73 - .../iq/config/CliStartupConfigOverrides.java | 71 - .../iq/config/CodeIqConfig.java | 166 - .../randomcodespace/iq/config/CorsConfig.java | 86 - .../iq/config/GraphBootstrapper.java | 122 - .../iq/config/JacksonConfig.java | 27 - .../iq/config/MapToJsonConverter.java | 47 - .../iq/config/Neo4jConfig.java | 86 - .../iq/config/ProjectConfigLoader.java | 46 - .../iq/config/UnifiedConfigAdapter.java | 73 - .../iq/config/UnifiedConfigBeans.java | 103 - .../iq/config/security/BearerAuthFilter.java | 176 - .../iq/config/security/RateLimitFilter.java | 171 - .../iq/config/security/RequestIdFilter.java | 81 - .../iq/config/security/SecurityConfig.java | 94 - .../security/SecurityHeadersFilter.java | 59 - .../iq/config/security/TokenResolver.java | 120 - .../config/unified/CodeIqUnifiedConfig.java | 28 - .../iq/config/unified/ConfigDefaults.java | 56 - .../iq/config/unified/ConfigError.java | 3 - .../iq/config/unified/ConfigLayer.java | 8 - .../config/unified/ConfigLoadException.java | 6 - .../iq/config/unified/ConfigMerger.java | 140 - .../iq/config/unified/ConfigProvenance.java | 3 - .../iq/config/unified/ConfigResolver.java | 46 - .../iq/config/unified/ConfigValidator.java | 118 - .../iq/config/unified/DetectorOverride.java | 4 - .../iq/config/unified/DetectorsConfig.java | 26 - .../iq/config/unified/EnvVarOverlay.java | 109 - .../iq/config/unified/IndexingConfig.java | 29 - .../iq/config/unified/McpAuthConfig.java | 33 - .../iq/config/unified/McpConfig.java | 7 - .../iq/config/unified/McpLimitsConfig.java | 25 - .../iq/config/unified/McpToolsConfig.java | 5 - .../iq/config/unified/MergedConfig.java | 5 - .../iq/config/unified/ModuleConfig.java | 2 - .../iq/config/unified/Neo4jConfig.java | 4 - .../config/unified/ObservabilityConfig.java | 4 - .../iq/config/unified/ProjectConfig.java | 5 - .../iq/config/unified/ServingConfig.java | 4 - .../config/unified/UnifiedConfigLoader.java | 262 -- .../iq/detector/AbstractAntlrDetector.java | 143 - .../iq/detector/AbstractRegexDetector.java | 94 - .../detector/AbstractStructuredDetector.java | 142 - .../randomcodespace/iq/detector/Detector.java | 28 - .../iq/detector/DetectorContext.java | 63 - .../iq/detector/DetectorDbHelper.java | 72 - .../iq/detector/DetectorEmissionDefaults.java | 61 - .../iq/detector/DetectorInfo.java | 23 - .../iq/detector/DetectorRegistry.java | 195 - .../iq/detector/DetectorResult.java | 21 - .../iq/detector/DetectorUtils.java | 213 - .../iq/detector/ParserType.java | 11 - .../iq/detector/StructuresDetectorHelper.java | 68 - .../auth/CertificateAuthDetector.java | 169 - .../iq/detector/auth/LdapAuthDetector.java | 124 - .../auth/SessionHeaderAuthDetector.java | 151 - .../detector/csharp/CSharpEfcoreDetector.java | 142 - .../csharp/CSharpMinimalApisDetector.java | 126 - .../csharp/CSharpStructuresDetector.java | 255 -- .../frontend/AngularComponentDetector.java | 137 - .../frontend/FrontendDetectorHelper.java | 44 - .../frontend/FrontendRouteDetector.java | 193 - .../frontend/ReactComponentDetector.java | 144 - .../frontend/SvelteComponentDetector.java | 105 - .../frontend/VueComponentDetector.java | 131 - .../generic/GenericImportsDetector.java | 206 - .../iq/detector/go/GoOrmDetector.java | 206 - .../iq/detector/go/GoStructuresDetector.java | 190 - .../iq/detector/go/GoWebDetector.java | 157 - .../iq/detector/iac/BicepDetector.java | 93 - .../iq/detector/iac/DockerfileDetector.java | 138 - .../iq/detector/iac/TerraformDetector.java | 144 - .../java/AbstractJavaMessagingDetector.java | 61 - .../jvm/java/AbstractJavaParserDetector.java | 65 - .../detector/jvm/java/ActiveMqDetector.java | 287 -- .../jvm/java/AzureFunctionsDetector.java | 219 - .../jvm/java/AzureMessagingDetector.java | 216 - .../jvm/java/ClassHierarchyDetector.java | 472 -- .../detector/jvm/java/ConfigDefDetector.java | 247 -- .../detector/jvm/java/CosmosDbDetector.java | 122 - .../jvm/java/GraphqlResolverDetector.java | 169 - .../jvm/java/GrpcServiceDetector.java | 139 - .../iq/detector/jvm/java/IbmMqDetector.java | 147 - .../iq/detector/jvm/java/JaxrsDetector.java | 159 - .../iq/detector/jvm/java/JdbcDetector.java | 201 - .../iq/detector/jvm/java/JmsDetector.java | 110 - .../detector/jvm/java/JpaEntityDetector.java | 403 -- .../iq/detector/jvm/java/KafkaDetector.java | 156 - .../jvm/java/KafkaProtocolDetector.java | 88 - .../detector/jvm/java/MicronautDetector.java | 250 -- .../detector/jvm/java/ModuleDepsDetector.java | 235 - .../detector/jvm/java/PublicApiDetector.java | 210 - .../iq/detector/jvm/java/QuarkusDetector.java | 153 - .../detector/jvm/java/RabbitmqDetector.java | 144 - .../iq/detector/jvm/java/RawSqlDetector.java | 142 - .../detector/jvm/java/RepositoryDetector.java | 234 - .../iq/detector/jvm/java/RmiDetector.java | 155 - .../jvm/java/SpringEventsDetector.java | 158 - .../detector/jvm/java/SpringRestDetector.java | 548 --- .../jvm/java/SpringSecurityDetector.java | 299 -- .../detector/jvm/java/TibcoEmsDetector.java | 180 - .../detector/jvm/java/WebSocketDetector.java | 196 - .../jvm/kotlin/KotlinStructuresDetector.java | 104 - .../jvm/kotlin/KtorRouteDetector.java | 147 - .../jvm/scala/ScalaStructuresDetector.java | 106 - .../markup/MarkdownStructureDetector.java | 111 - .../proto/ProtoStructureDetector.java | 134 - .../python/AbstractPythonAntlrDetector.java | 62 - .../python/AbstractPythonDbDetector.java | 42 - .../detector/python/CeleryTaskDetector.java | 213 - .../detector/python/DjangoAuthDetector.java | 231 - .../detector/python/DjangoModelDetector.java | 295 -- .../detector/python/DjangoViewDetector.java | 141 - .../detector/python/FastAPIAuthDetector.java | 220 - .../detector/python/FastAPIRouteDetector.java | 180 - .../detector/python/FlaskRouteDetector.java | 207 - .../detector/python/KafkaPythonDetector.java | 222 - .../python/PydanticModelDetector.java | 215 - .../python/PythonStructuresDetector.java | 466 -- .../python/SQLAlchemyModelDetector.java | 172 - .../detector/script/shell/BashDetector.java | 108 - .../script/shell/PowerShellDetector.java | 98 - .../iq/detector/sql/SqlMigrationDetector.java | 550 --- .../iq/detector/sql/package-info.java | 8 - .../structured/BatchStructureDetector.java | 136 - .../structured/CloudFormationDetector.java | 211 - .../structured/DockerComposeDetector.java | 242 -- .../structured/GitHubActionsDetector.java | 193 - .../detector/structured/GitLabCiDetector.java | 247 -- .../structured/HelmChartDetector.java | 202 - .../structured/IniStructureDetector.java | 116 - .../structured/JsonStructureDetector.java | 75 - .../structured/KubernetesDetector.java | 357 -- .../structured/KubernetesRbacDetector.java | 234 - .../detector/structured/OpenApiDetector.java | 214 - .../structured/PackageJsonDetector.java | 135 - .../structured/PropertiesDetector.java | 166 - .../structured/PyprojectTomlDetector.java | 182 - .../structured/SqlStructureDetector.java | 159 - .../structured/TomlStructureDetector.java | 98 - .../structured/TsconfigJsonDetector.java | 142 - .../structured/YamlStructureDetector.java | 88 - .../systems/cpp/CppStructuresDetector.java | 153 - .../systems/rust/ActixWebDetector.java | 196 - .../systems/rust/RustStructuresDetector.java | 146 - .../AbstractTypeScriptDetector.java | 18 - .../typescript/ExpressRouteDetector.java | 71 - .../typescript/FastifyRouteDetector.java | 189 - .../typescript/GraphQLResolverDetector.java | 128 - .../detector/typescript/KafkaJSDetector.java | 184 - .../typescript/MongooseORMDetector.java | 187 - .../typescript/NestJSControllerDetector.java | 212 - .../typescript/NestJSGuardsDetector.java | 173 - .../typescript/PassportJwtDetector.java | 156 - .../typescript/PrismaORMDetector.java | 130 - .../typescript/RemixRouteDetector.java | 177 - .../typescript/SequelizeORMDetector.java | 165 - .../typescript/TypeORMEntityDetector.java | 123 - .../TypeScriptStructuresDetector.java | 413 -- .../iq/flow/CacheFlowDataSource.java | 35 - .../iq/flow/FlowDataSource.java | 19 - .../randomcodespace/iq/flow/FlowEngine.java | 125 - .../randomcodespace/iq/flow/FlowModels.java | 154 - .../randomcodespace/iq/flow/FlowRenderer.java | 188 - .../randomcodespace/iq/flow/FlowViews.java | 579 --- .../iq/grammar/AntlrParserFactory.java | 228 - .../iq/grammar/cpp/CPP14ParserBase.java | 28 - .../iq/grammar/csharp/CSharpLexerBase.java | 105 - .../iq/grammar/csharp/CSharpParserBase.java | 24 - .../csharp/CSharpPreprocessorParserBase.java | 205 - .../iq/grammar/golang/GoParserBase.java | 195 - .../javascript/JavaScriptLexerBase.java | 167 - .../javascript/JavaScriptParserBase.java | 99 - .../iq/grammar/python/Python3LexerBase.java | 154 - .../iq/grammar/python/Python3ParserBase.java | 21 - .../iq/grammar/rust/RustLexerBase.java | 102 - .../iq/grammar/rust/RustParserBase.java | 17 - .../typescript/TypeScriptLexerBase.java | 167 - .../typescript/TypeScriptParserBase.java | 124 - .../iq/graph/GraphRepository.java | 88 - .../randomcodespace/iq/graph/GraphStore.java | 1318 ------ .../iq/health/GraphHealthIndicator.java | 103 - .../iq/intelligence/ArtifactManifest.java | 80 - .../iq/intelligence/CapabilityLevel.java | 16 - .../iq/intelligence/FileClassification.java | 18 - .../iq/intelligence/FileEntry.java | 61 - .../iq/intelligence/FileInventory.java | 72 - .../iq/intelligence/Provenance.java | 65 - .../iq/intelligence/RepositoryIdentity.java | 60 - .../intelligence/evidence/EvidencePack.java | 41 - .../evidence/EvidencePackAssembler.java | 267 -- .../evidence/EvidencePackRequest.java | 21 - .../extractor/LanguageEnricher.java | 252 -- .../extractor/LanguageExtractionResult.java | 34 - .../extractor/LanguageExtractor.java | 37 - .../extractor/go/GoLanguageExtractor.java | 199 - .../extractor/java/JavaLanguageExtractor.java | 150 - .../python/PythonLanguageExtractor.java | 168 - .../TypeScriptLanguageExtractor.java | 144 - .../iq/intelligence/lexical/CodeSnippet.java | 22 - .../lexical/DocCommentExtractor.java | 193 - .../intelligence/lexical/LexicalEnricher.java | 134 - .../lexical/LexicalQueryService.java | 107 - .../intelligence/lexical/LexicalResult.java | 27 - .../iq/intelligence/lexical/SnippetStore.java | 106 - .../provenance/ArtifactMetadata.java | 53 - .../provenance/ArtifactMetadataProvider.java | 71 - .../query/CapabilityDimension.java | 26 - .../intelligence/query/CapabilityMatrix.java | 294 -- .../iq/intelligence/query/QueryPlan.java | 43 - .../iq/intelligence/query/QueryPlanner.java | 142 - .../iq/intelligence/query/QueryRoute.java | 28 - .../iq/intelligence/query/QueryType.java | 20 - .../intelligence/resolver/EmptyResolved.java | 34 - .../resolver/ResolutionException.java | 48 - .../iq/intelligence/resolver/Resolved.java | 38 - .../resolver/ResolverRegistry.java | 107 - .../intelligence/resolver/SymbolResolver.java | 77 - .../resolver/java/JavaResolved.java | 32 - .../java/JavaSourceRootDiscovery.java | 137 - .../resolver/java/JavaSymbolResolver.java | 143 - .../randomcodespace/iq/mcp/McpTools.java | 735 ---- .../randomcodespace/iq/model/CodeEdge.java | 153 - .../randomcodespace/iq/model/CodeNode.java | 242 -- .../randomcodespace/iq/model/Confidence.java | 59 - .../iq/model/ConfidenceConverter.java | 24 - .../randomcodespace/iq/model/EdgeKind.java | 71 - .../iq/model/EdgeKindConverter.java | 22 - .../randomcodespace/iq/model/NodeKind.java | 77 - .../iq/model/NodeKindConverter.java | 22 - .../iq/query/QueryService.java | 654 --- .../iq/query/StatsService.java | 392 -- .../iq/query/TopologyService.java | 569 --- .../iq/query/TopologySnapshotProvider.java | 119 - .../randomcodespace/iq/web/SpaController.java | 47 - src/main/resources/application.yml | 187 - src/main/resources/logback-spring.xml | 85 - ...BricolageGrotesque-Variable-C5Lc8Qmc.woff2 | Bin 131548 -> 0 bytes .../assets/GeistMono-Variable-BNLlm6Cd.woff2 | Bin 71004 -> 0 bytes .../PlusJakartaSans-Variable-eXO_dkmS.woff2 | Bin 27348 -> 0 bytes .../static/assets/design-system-BIHI7g3E.js | 1 - .../static/assets/design-system-Df6KNeSA.js | 1 - .../static/assets/tesselator-D_j4OGEy.js | 1916 --------- src/main/resources/static/css/explorer.css | 1 - src/main/resources/static/favicon.svg | 4 - .../static/js/vendor/cytoscape-dagre.min.js | 8 - .../static/js/vendor/cytoscape.min.js | 32 - .../resources/static/js/vendor/dagre.min.js | 3809 ----------------- .../resources/templates/flow/interactive.html | 252 -- .../iq/CodeIqApplicationArgParsingTest.java | 52 - .../iq/CodeIqApplicationTest.java | 52 - .../analyzer/AnalyzerBoundedExecutorTest.java | 113 - .../analyzer/AnalyzerResolverWiringTest.java | 230 - .../iq/analyzer/AnalyzerTest.java | 206 - .../ArchitectureKeywordFilterTest.java | 274 -- .../iq/analyzer/BatchedStreamingTest.java | 184 - .../iq/analyzer/ConfigScannerTest.java | 371 -- .../iq/analyzer/FileDiscoveryTest.java | 287 -- .../analyzer/FullAnalysisIntegrationTest.java | 389 -- .../iq/analyzer/GraphBuilderTest.java | 142 - .../analyzer/InfrastructureRegistryTest.java | 130 - .../iq/analyzer/LayerClassifierTest.java | 451 -- .../iq/analyzer/ServiceDetectorTest.java | 563 --- .../iq/analyzer/SmartIndexTest.java | 305 -- .../iq/analyzer/StructuredParserTest.java | 198 - .../iq/analyzer/linker/EntityLinkerTest.java | 113 - .../iq/analyzer/linker/GuardLinkerTest.java | 145 - .../analyzer/linker/LinkersCoverageTest.java | 377 -- .../linker/ModuleContainmentLinkerTest.java | 118 - .../iq/analyzer/linker/TopicLinkerTest.java | 379 -- .../iq/api/FlowControllerTest.java | 127 - .../iq/api/GlobalExceptionHandlerTest.java | 83 - .../iq/api/GraphControllerTest.java | 701 --- .../iq/api/IntelligenceControllerTest.java | 155 - .../iq/api/SafeFileReaderTest.java | 68 - .../api/TopologyControllerExtendedTest.java | 363 -- .../iq/api/TopologyControllerTest.java | 102 - .../iq/api/TopologyEndpointTest.java | 240 -- .../iq/benchmark/AnalysisBenchmarkTest.java | 188 - .../cache/AnalysisCacheBatchReplaceTest.java | 229 - .../iq/cache/AnalysisCacheConfidenceTest.java | 207 - .../iq/cache/AnalysisCacheTest.java | 168 - .../iq/cache/CacheCoverageTest.java | 244 -- .../iq/cache/FileHasherTest.java | 62 - .../iq/cli/AnalyzeCommandTest.java | 159 - .../iq/cli/BundleCommandExtendedTest.java | 260 -- .../iq/cli/BundleCommandTest.java | 224 - .../iq/cli/CacheCommandTest.java | 103 - .../iq/cli/CliExtendedTest.java | 487 --- .../randomcodespace/iq/cli/CodeIqCliTest.java | 53 - .../iq/cli/ConfigExplainSubcommandTest.java | 223 - .../iq/cli/ConfigValidateSubcommandTest.java | 153 - .../iq/cli/CypherCommandTest.java | 42 - .../iq/cli/EnrichCommandTest.java | 159 - .../iq/cli/FindCommandTest.java | 51 - .../iq/cli/FlowCommandExtendedTest.java | 166 - .../iq/cli/FlowCommandTest.java | 152 - .../iq/cli/GraphCommandTest.java | 123 - .../iq/cli/IndexCommandTest.java | 145 - .../iq/cli/PluginsCommandTest.java | 226 - .../iq/cli/QueryCommandTest.java | 97 - .../iq/cli/ServeCommandTest.java | 109 - .../iq/cli/StatsCommandTest.java | 244 -- .../iq/cli/TopologyCommandExtendedTest.java | 269 -- .../iq/cli/TopologyCommandTest.java | 67 - .../iq/cli/VersionCommandTest.java | 57 - .../config/CliStartupConfigOverridesTest.java | 104 - .../iq/config/CodeIqConfigTest.java | 187 - .../iq/config/CodeIqConfigTestSupport.java | 54 - .../iq/config/CorsConfigTest.java | 143 - .../iq/config/GraphBootstrapperTest.java | 154 - .../iq/config/JacksonConfigTest.java | 25 - .../iq/config/MapToJsonConverterTest.java | 79 - .../iq/config/ProjectConfigLoaderTest.java | 26 - .../iq/config/UnifiedConfigAdapterTest.java | 190 - .../iq/config/UnifiedConfigBeansTest.java | 122 - .../config/security/BearerAuthFilterTest.java | 239 -- .../config/security/RateLimitFilterTest.java | 161 - .../config/security/RequestIdFilterTest.java | 160 - .../security/SecurityHeadersFilterTest.java | 62 - .../security/ServingChainIntegrationTest.java | 215 - .../iq/config/security/TokenResolverTest.java | 137 - .../unified/CodeIqUnifiedConfigTest.java | 17 - .../iq/config/unified/ConfigDefaultsTest.java | 38 - .../iq/config/unified/ConfigMergerTest.java | 113 - .../iq/config/unified/ConfigResolverTest.java | 50 - .../config/unified/ConfigValidatorTest.java | 68 - .../unified/EnvVarOverlayExtendedTest.java | 264 -- .../iq/config/unified/EnvVarOverlayTest.java | 90 - .../unified/UnifiedConfigLoaderTest.java | 327 -- .../deploy/AksLaunchScriptSentinelTest.java | 132 - .../AbstractAntlrDetectorHelperTest.java | 156 - .../detector/AbstractRegexDetectorTest.java | 123 - .../AbstractStructuredDetectorTest.java | 181 - .../iq/detector/AntlrInfrastructureTest.java | 289 -- .../detector/DetectorContextResolvedTest.java | 140 - .../iq/detector/DetectorContextTest.java | 39 - .../DetectorEmissionDefaultsTest.java | 253 -- .../detector/DetectorInfoAnnotationTest.java | 114 - .../iq/detector/DetectorRegistryTest.java | 202 - .../iq/detector/DetectorResultTest.java | 56 - .../iq/detector/DetectorTestUtils.java | 64 - .../iq/detector/DetectorUtilsTest.java | 203 - .../iq/detector/LanguageMappingTest.java | 108 - .../auth/AuthDetectorsCoverageTest.java | 471 -- .../auth/CertificateAuthDetectorTest.java | 31 - .../detector/auth/LdapAuthDetectorTest.java | 30 - .../auth/SessionHeaderAuthDetectorTest.java | 30 - .../csharp/CSharpDetectorsCoverageTest.java | 413 -- .../csharp/CSharpDetectorsExtendedTest.java | 199 - .../csharp/CSharpEfcoreDetectorTest.java | 11 - .../csharp/CSharpMinimalApisDetectorTest.java | 11 - .../csharp/CSharpStructuresDetectorTest.java | 11 - .../AngularComponentDetectorTest.java | 12 - .../FrontendDetectorsCoverageTest.java | 570 --- .../FrontendDetectorsExtendedTest.java | 384 -- .../frontend/FrontendRouteDetectorTest.java | 14 - .../frontend/ReactComponentDetectorTest.java | 135 - .../frontend/SvelteComponentDetectorTest.java | 11 - .../frontend/VueComponentDetectorTest.java | 14 - .../generic/GenericImportsDetectorTest.java | 11 - .../generic/GenericImportsExtendedTest.java | 125 - .../detector/go/GoDetectorsExtendedTest.java | 231 - .../iq/detector/go/GoOrmDetectorTest.java | 164 - .../detector/go/GoStructuresDetectorTest.java | 183 - .../iq/detector/go/GoWebDetectorTest.java | 158 - .../iq/detector/iac/BicepDetectorTest.java | 11 - .../detector/iac/DockerfileDetectorTest.java | 11 - .../iac/IacDetectorsExtendedTest.java | 215 - .../detector/iac/TerraformDetectorTest.java | 11 - .../jvm/java/ActiveMqDetectorTest.java | 323 -- .../jvm/java/AzureFunctionsDetectorTest.java | 306 -- .../jvm/java/AzureMessagingDetectorTest.java | 388 -- .../ClassHierarchyDetectorExtendedTest.java | 424 -- .../ClassHierarchyDetectorResolvedTest.java | 223 - .../jvm/java/ConfigDefDetectorTest.java | 351 -- .../java/JavaDetectorsBranchCoverageTest.java | 1546 ------- .../jvm/java/JavaDetectorsCoverageTest.java | 1808 -------- .../jvm/java/JavaDetectorsExtendedTest.java | 938 ---- .../detector/jvm/java/JavaDetectorsTest.java | 1056 ----- .../java/JpaEntityDetectorExtendedTest.java | 570 --- .../java/JpaEntityDetectorResolvedTest.java | 293 -- .../jvm/java/ModuleDepsDetectorTest.java | 390 -- .../jvm/java/PublicApiDetectorTest.java | 549 --- .../java/RepositoryDetectorResolvedTest.java | 225 - .../java/SpringRestDetectorExtendedTest.java | 488 --- .../java/SpringRestDetectorResolvedTest.java | 226 - .../SpringSecurityDetectorExtendedTest.java | 506 --- .../kotlin/KotlinStructuresDetectorTest.java | 141 - .../jvm/kotlin/KtorRouteDetectorTest.java | 148 - .../scala/ScalaStructuresDetectorTest.java | 130 - .../markup/MarkdownStructureDetectorTest.java | 144 - .../proto/ProtoStructureDetectorTest.java | 181 - .../CeleryTaskDetectorExtendedTest.java | 413 -- .../python/CeleryTaskDetectorTest.java | 285 -- .../python/DjangoAuthDetectorTest.java | 314 -- .../DjangoModelDetectorExtendedTest.java | 367 -- .../python/DjangoModelDetectorTest.java | 304 -- .../python/DjangoViewDetectorTest.java | 286 -- .../FastAPIAuthDetectorExtendedTest.java | 318 -- .../python/FastAPIAuthDetectorTest.java | 275 -- .../python/FastAPIRouteDetectorTest.java | 281 -- .../python/FlaskRouteDetectorTest.java | 257 -- .../python/KafkaPythonDetectorTest.java | 70 - .../PydanticModelDetectorExtendedTest.java | 408 -- .../python/PydanticModelDetectorTest.java | 311 -- .../PythonStructuresDetectorExtendedTest.java | 466 -- .../python/PythonStructuresDetectorTest.java | 411 -- .../SQLAlchemyModelDetectorExtendedTest.java | 369 -- .../python/SQLAlchemyModelDetectorTest.java | 283 -- .../script/shell/BashDetectorTest.java | 170 - .../script/shell/PowerShellDetectorTest.java | 127 - .../sql/SqlMigrationDetectorTest.java | 405 -- .../BatchStructureDetectorTest.java | 57 - .../CloudFormationDetectorTest.java | 80 - .../ConfigDetectorsExtendedTest.java | 232 - .../structured/DockerComposeDetectorTest.java | 77 - .../structured/GitHubActionsDetectorTest.java | 82 - .../structured/GitLabCiDetectorTest.java | 83 - .../structured/HelmChartDetectorTest.java | 83 - .../structured/IniStructureDetectorTest.java | 56 - .../structured/JsonStructureDetectorTest.java | 50 - .../KubernetesDetectorExpandedTest.java | 449 -- .../structured/KubernetesDetectorTest.java | 94 - .../KubernetesRbacDetectorTest.java | 71 - .../structured/OpenApiDetectorTest.java | 93 - .../structured/PackageJsonDetectorTest.java | 59 - .../structured/PropertiesDetectorTest.java | 122 - .../structured/PyprojectTomlDetectorTest.java | 69 - .../structured/SqlStructureDetectorTest.java | 68 - .../structured/TomlStructureDetectorTest.java | 56 - .../structured/TsconfigJsonDetectorTest.java | 65 - .../structured/YamlStructureDetectorTest.java | 66 - .../cpp/CppStructuresDetectorTest.java | 128 - .../systems/rust/ActixWebDetectorTest.java | 153 - .../rust/RustDetectorsExtendedTest.java | 158 - .../rust/RustStructuresDetectorTest.java | 144 - .../ExpressRouteDetectorExtendedTest.java | 268 -- .../typescript/ExpressRouteDetectorTest.java | 151 - .../typescript/FastifyRouteDetectorTest.java | 181 - .../GraphQLResolverDetectorTest.java | 180 - .../typescript/KafkaJSDetectorTest.java | 163 - .../typescript/MongooseORMDetectorTest.java | 176 - .../NestJSControllerDetectorTest.java | 232 - .../typescript/NestJSGuardsDetectorTest.java | 204 - .../typescript/PassportJwtDetectorTest.java | 157 - .../typescript/PrismaORMDetectorTest.java | 171 - .../typescript/RemixRouteDetectorTest.java | 189 - .../typescript/SequelizeORMDetectorTest.java | 164 - .../typescript/TypeORMEntityDetectorTest.java | 206 - .../TypeScriptDetectorsExtendedTest.java | 153 - .../TypeScriptStructuresDetectorTest.java | 232 - .../iq/e2e/E2EQualityTest.java | 751 ---- .../iq/e2e/IntegrationSmokeTest.java | 237 - .../iq/flow/CacheFlowDataSourceTest.java | 79 - .../iq/flow/FlowEngineExtendedTest.java | 256 -- .../iq/flow/FlowEngineTest.java | 244 -- .../iq/flow/FlowRendererTest.java | 210 - .../iq/flow/FlowViewsTest.java | 568 --- .../graph/GraphStoreAggregateStatsTest.java | 342 -- .../GraphStoreConfidenceRoundTripTest.java | 340 -- .../iq/graph/GraphStoreExtendedTest.java | 335 -- .../iq/graph/GraphStoreTest.java | 151 - .../graph/GraphStoreTopologyAndStatsTest.java | 747 ---- .../iq/health/GraphHealthIndicatorTest.java | 77 - .../iq/intelligence/ArtifactManifestTest.java | 64 - .../iq/intelligence/FileInventoryTest.java | 109 - .../intelligence/ProvenanceEdgeCasesTest.java | 210 - .../ProvenanceIntegrationTest.java | 100 - .../ProvenanceNeo4jRoundTripTest.java | 162 - .../iq/intelligence/ProvenanceTest.java | 81 - .../intelligence/RepositoryIdentityTest.java | 210 - .../EvidencePackAssemblerExtendedTest.java | 441 -- .../evidence/EvidencePackAssemblerTest.java | 127 - .../LanguageEnricherExtendedTest.java | 377 -- .../extractor/LanguageEnricherTest.java | 224 - .../extractor/go/GoLanguageExtractorTest.java | 268 -- .../java/JavaLanguageExtractorTest.java | 167 - .../python/PythonLanguageExtractorTest.java | 182 - .../TypeScriptLanguageExtractorTest.java | 139 - .../lexical/DocCommentExtractorTest.java | 125 - .../lexical/LexicalCrossLanguageTest.java | 272 -- .../lexical/LexicalEnricherTest.java | 110 - .../lexical/LexicalQueryServiceTest.java | 203 - .../lexical/SnippetStoreTest.java | 118 - .../ArtifactMetadataProviderTest.java | 47 - .../provenance/ArtifactMetadataTest.java | 98 - .../query/CapabilityMatrixTest.java | 167 - .../query/QueryIntelligenceCoverageTest.java | 295 -- .../intelligence/query/QueryPlannerTest.java | 212 - .../resolver/ResolutionExceptionTest.java | 55 - .../resolver/ResolvedContractTest.java | 68 - .../resolver/ResolverRegistryTest.java | 206 - .../resolver/SymbolResolverContractTest.java | 126 - .../java/E2EResolverPetclinicTest.java | 96 - .../resolver/java/JavaResolvedTest.java | 73 - .../java/JavaSourceRootDiscoveryTest.java | 241 -- .../JavaSymbolResolverAdversarialTest.java | Bin 5880 -> 0 bytes .../JavaSymbolResolverConcurrencyTest.java | 196 - .../JavaSymbolResolverDeterminismTest.java | 187 - .../JavaSymbolResolverLayer1ExtendedTest.java | 261 -- .../JavaSymbolResolverPathologicalTest.java | 104 - .../JavaSymbolResolverRandomizedTest.java | 143 - .../resolver/java/JavaSymbolResolverTest.java | 326 -- .../iq/mcp/McpToolsEvidenceTest.java | 118 - .../iq/mcp/McpToolsExpandedTest.java | 622 --- .../randomcodespace/iq/mcp/McpToolsTest.java | 621 --- .../iq/model/CodeEdgeConfidenceTest.java | 60 - .../iq/model/CodeNodeConfidenceTest.java | 56 - .../iq/model/CodeNodeEdgeExtendedTest.java | 146 - .../iq/model/ConfidenceTest.java | 40 - .../iq/model/EdgeKindTest.java | 42 - .../iq/model/KindConverterTest.java | 120 - .../iq/model/ModelCoverageTest.java | 649 --- .../iq/model/NodeKindTest.java | 43 - .../iq/query/QueryServiceTest.java | 846 ---- .../iq/query/StatsServiceTest.java | 435 -- .../iq/query/TopologyServiceTest.java | 230 - .../iq/web/SpaControllerConditionalTest.java | 84 - .../iq/web/SpaControllerMockMvcTest.java | 75 - src/test/resources/application-test.yml | 10 - src/test/resources/config-unified/full.yml | 56 - .../resources/config-unified/malformed.yml | 4 - src/test/resources/config-unified/minimal.yml | 4 - .../resources/e2e/ground-truth-petclinic.json | 44 - .../e2e/ground-truth-realworld-express.json | 17 - 646 files changed, 719 insertions(+), 133132 deletions(-) delete mode 100644 .github/workflows/beta-java.yml delete mode 100644 .github/workflows/ci-java.yml delete mode 100644 .github/workflows/go-parity.yml delete mode 100644 .github/workflows/release-java.yml delete mode 100644 pom.xml delete mode 100644 spotbugs-exclude.xml delete mode 100644 src/assembly/source-bundle.xml delete mode 100644 src/main/antlr4/imports/UnicodeClasses.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Lexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Parser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpLexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpParser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpPreprocessorParser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoLexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoParser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptLexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptParser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinLexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinParser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/UnicodeClasses.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Lexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Parser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustLexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustParser.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/scala/Scala.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptLexer.g4 delete mode 100644 src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptParser.g4 delete mode 100644 src/main/frontend/.gitignore delete mode 100644 src/main/frontend/index.html delete mode 100644 src/main/frontend/package-lock.json delete mode 100644 src/main/frontend/package.json delete mode 100644 src/main/frontend/playwright-report/data/52d6e968bcc3e3f9fb8eaecdf7ea2f3d2ab41deb.png delete mode 100644 src/main/frontend/playwright-report/data/813e22f62153becae158a32a0ef8aa8037da1508.webm delete mode 100644 src/main/frontend/playwright-report/data/8c72b585fa3d6ad6b85b44878d2427a335bdf9de.md delete mode 100644 src/main/frontend/playwright-report/data/b2072c8aa5cd97f91093ec8cad3e5f7b48b55c66.md delete mode 100644 src/main/frontend/playwright-report/data/f1d00512fbfc05f51c50987f6e805c0156f31b2d.png delete mode 100644 src/main/frontend/playwright-report/data/f6eb10ff67df8fe6b39c93a7519699a0d4e67b55.webm delete mode 100644 src/main/frontend/playwright-report/index.html delete mode 100644 src/main/frontend/playwright.config.ts delete mode 100644 src/main/frontend/public/favicon.svg delete mode 100644 src/main/frontend/src/App.tsx delete mode 100644 src/main/frontend/src/components/AppLayout.tsx delete mode 100644 src/main/frontend/src/components/Icons.tsx delete mode 100644 src/main/frontend/src/context/ThemeContext.tsx delete mode 100644 src/main/frontend/src/env.d.ts delete mode 100644 src/main/frontend/src/hooks/useApi.ts delete mode 100644 src/main/frontend/src/index.css delete mode 100644 src/main/frontend/src/lib/api.ts delete mode 100644 src/main/frontend/src/lib/mcp-tools.ts delete mode 100644 src/main/frontend/src/main.tsx delete mode 100644 src/main/frontend/src/pages/Dashboard.tsx delete mode 100644 src/main/frontend/src/types/api.ts delete mode 100644 src/main/frontend/test-results/.last-run.json delete mode 100644 src/main/frontend/tests/e2e/accessibility.spec.ts delete mode 100644 src/main/frontend/tests/e2e/edge-cases.spec.ts delete mode 100644 src/main/frontend/tests/e2e/file-tree.spec.ts delete mode 100644 src/main/frontend/tests/e2e/graph.spec.ts delete mode 100644 src/main/frontend/tests/e2e/mcp-console.spec.ts delete mode 100644 src/main/frontend/tests/e2e/navigation.spec.ts delete mode 100644 src/main/frontend/tests/e2e/performance.spec.ts delete mode 100644 src/main/frontend/tests/e2e/responsive.spec.ts delete mode 100644 src/main/frontend/tests/e2e/search.spec.ts delete mode 100644 src/main/frontend/tests/utils/test-helpers.ts delete mode 100644 src/main/frontend/tsconfig.json delete mode 100644 src/main/frontend/tsconfig.test.json delete mode 100644 src/main/frontend/vite.config.ts delete mode 100644 src/main/java/io/github/randomcodespace/iq/CodeIqApplication.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/AnalysisResult.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/Analyzer.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/ArchitectureKeywordFilter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/ConfigScanner.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/DiscoveredFile.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/FileClassifier.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/FileDiscovery.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/GraphBuilder.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/InfraEndpoint.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/InfrastructureRegistry.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/LayerClassifier.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/ServiceDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/StructuredParser.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/linker/EntityLinker.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/linker/GuardLinker.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/linker/LinkResult.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/linker/Linker.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/linker/ModuleContainmentLinker.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/analyzer/linker/TopicLinker.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/api/FlowController.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/api/GlobalExceptionHandler.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/api/GraphController.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/api/IntelligenceController.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/api/SafeFileReader.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/api/TopologyController.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cache/AnalysisCache.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cache/FileHasher.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/AnalyzeCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/BundleCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/CacheCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/CliOutput.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/CodeIqCli.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/ConfigCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/ConfigExplainSubcommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/ConfigValidateSubcommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/CypherCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/EnrichCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/FindCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/FlowCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/GraphCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/IndexCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/PluginsCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/QueryCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/ServeCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/StatsCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/TopologyCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/cli/VersionCommand.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/CliStartupConfigOverrides.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/CodeIqConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/CorsConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/GraphBootstrapper.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/JacksonConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/MapToJsonConverter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/Neo4jConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/ProjectConfigLoader.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/UnifiedConfigAdapter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/UnifiedConfigBeans.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/security/BearerAuthFilter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/security/RateLimitFilter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/security/RequestIdFilter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/security/SecurityConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/security/SecurityHeadersFilter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/security/TokenResolver.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/CodeIqUnifiedConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigDefaults.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigError.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigLayer.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigLoadException.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigMerger.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigProvenance.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigResolver.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ConfigValidator.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/DetectorOverride.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/DetectorsConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/EnvVarOverlay.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/IndexingConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/McpAuthConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/McpConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/McpLimitsConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/McpToolsConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/MergedConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ModuleConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/Neo4jConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ObservabilityConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ProjectConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/ServingConfig.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/config/unified/UnifiedConfigLoader.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/AbstractAntlrDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/AbstractRegexDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/AbstractStructuredDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/Detector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorContext.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorDbHelper.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorEmissionDefaults.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorInfo.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorRegistry.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorResult.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/DetectorUtils.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/ParserType.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/StructuresDetectorHelper.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/auth/CertificateAuthDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/auth/LdapAuthDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/auth/SessionHeaderAuthDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/csharp/CSharpEfcoreDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/csharp/CSharpMinimalApisDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/csharp/CSharpStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/frontend/AngularComponentDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/frontend/FrontendDetectorHelper.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/frontend/FrontendRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/frontend/ReactComponentDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/frontend/SvelteComponentDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/frontend/VueComponentDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/generic/GenericImportsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/go/GoOrmDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/go/GoStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/go/GoWebDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/iac/BicepDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/iac/DockerfileDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/iac/TerraformDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/AbstractJavaMessagingDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/AbstractJavaParserDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/ActiveMqDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/AzureFunctionsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/AzureMessagingDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/ClassHierarchyDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/ConfigDefDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/CosmosDbDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/GraphqlResolverDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/GrpcServiceDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/IbmMqDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/JaxrsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/JdbcDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/JmsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/JpaEntityDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/KafkaDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/KafkaProtocolDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/MicronautDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/ModuleDepsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/PublicApiDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/QuarkusDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/RabbitmqDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/RawSqlDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/RepositoryDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/RmiDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/SpringEventsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/SpringRestDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/SpringSecurityDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/TibcoEmsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/java/WebSocketDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/kotlin/KotlinStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/kotlin/KtorRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/jvm/scala/ScalaStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/markup/MarkdownStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/proto/ProtoStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/AbstractPythonAntlrDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/AbstractPythonDbDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/CeleryTaskDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/DjangoAuthDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/DjangoModelDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/DjangoViewDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/FastAPIAuthDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/FastAPIRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/FlaskRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/KafkaPythonDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/PydanticModelDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/PythonStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/python/SQLAlchemyModelDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/script/shell/BashDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/script/shell/PowerShellDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/sql/SqlMigrationDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/sql/package-info.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/BatchStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/CloudFormationDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/DockerComposeDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/GitHubActionsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/GitLabCiDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/HelmChartDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/IniStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/JsonStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/KubernetesDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/KubernetesRbacDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/OpenApiDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/PackageJsonDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/PropertiesDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/PyprojectTomlDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/SqlStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/TomlStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/TsconfigJsonDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/structured/YamlStructureDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/systems/cpp/CppStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/systems/rust/ActixWebDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/systems/rust/RustStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/AbstractTypeScriptDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/ExpressRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/FastifyRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/GraphQLResolverDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/KafkaJSDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/MongooseORMDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/NestJSControllerDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/NestJSGuardsDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/PassportJwtDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/PrismaORMDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/RemixRouteDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/SequelizeORMDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/TypeORMEntityDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/detector/typescript/TypeScriptStructuresDetector.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/flow/CacheFlowDataSource.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/flow/FlowDataSource.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/flow/FlowEngine.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/flow/FlowModels.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/flow/FlowRenderer.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/flow/FlowViews.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/AntlrParserFactory.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/cpp/CPP14ParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/csharp/CSharpLexerBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/csharp/CSharpParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/csharp/CSharpPreprocessorParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/golang/GoParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/javascript/JavaScriptLexerBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/javascript/JavaScriptParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/python/Python3LexerBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/python/Python3ParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/rust/RustLexerBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/rust/RustParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/typescript/TypeScriptLexerBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/grammar/typescript/TypeScriptParserBase.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/graph/GraphRepository.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/graph/GraphStore.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/health/GraphHealthIndicator.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/ArtifactManifest.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/CapabilityLevel.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/FileClassification.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/FileEntry.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/FileInventory.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/Provenance.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/RepositoryIdentity.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/evidence/EvidencePack.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/evidence/EvidencePackAssembler.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/evidence/EvidencePackRequest.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/LanguageEnricher.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/LanguageExtractionResult.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/LanguageExtractor.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/go/GoLanguageExtractor.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/java/JavaLanguageExtractor.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/python/PythonLanguageExtractor.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/extractor/typescript/TypeScriptLanguageExtractor.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/lexical/CodeSnippet.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/lexical/DocCommentExtractor.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/lexical/LexicalEnricher.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/lexical/LexicalQueryService.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/lexical/LexicalResult.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/lexical/SnippetStore.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/provenance/ArtifactMetadata.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/provenance/ArtifactMetadataProvider.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/query/CapabilityDimension.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/query/CapabilityMatrix.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/query/QueryPlan.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/query/QueryPlanner.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/query/QueryRoute.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/query/QueryType.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/EmptyResolved.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/ResolutionException.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/Resolved.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/ResolverRegistry.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/SymbolResolver.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaResolved.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSourceRootDiscovery.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolver.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/mcp/McpTools.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/CodeEdge.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/CodeNode.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/Confidence.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/ConfidenceConverter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/EdgeKind.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/EdgeKindConverter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/NodeKind.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/model/NodeKindConverter.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/query/QueryService.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/query/StatsService.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/query/TopologyService.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/query/TopologySnapshotProvider.java delete mode 100644 src/main/java/io/github/randomcodespace/iq/web/SpaController.java delete mode 100644 src/main/resources/application.yml delete mode 100644 src/main/resources/logback-spring.xml delete mode 100644 src/main/resources/static/assets/BricolageGrotesque-Variable-C5Lc8Qmc.woff2 delete mode 100644 src/main/resources/static/assets/GeistMono-Variable-BNLlm6Cd.woff2 delete mode 100644 src/main/resources/static/assets/PlusJakartaSans-Variable-eXO_dkmS.woff2 delete mode 100644 src/main/resources/static/assets/design-system-BIHI7g3E.js delete mode 100644 src/main/resources/static/assets/design-system-Df6KNeSA.js delete mode 100644 src/main/resources/static/assets/tesselator-D_j4OGEy.js delete mode 100644 src/main/resources/static/css/explorer.css delete mode 100644 src/main/resources/static/favicon.svg delete mode 100644 src/main/resources/static/js/vendor/cytoscape-dagre.min.js delete mode 100644 src/main/resources/static/js/vendor/cytoscape.min.js delete mode 100644 src/main/resources/static/js/vendor/dagre.min.js delete mode 100644 src/main/resources/templates/flow/interactive.html delete mode 100644 src/test/java/io/github/randomcodespace/iq/CodeIqApplicationArgParsingTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/CodeIqApplicationTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/AnalyzerBoundedExecutorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/AnalyzerResolverWiringTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/AnalyzerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/ArchitectureKeywordFilterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/BatchedStreamingTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/ConfigScannerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/FileDiscoveryTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/FullAnalysisIntegrationTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/GraphBuilderTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/InfrastructureRegistryTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/LayerClassifierTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/ServiceDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/SmartIndexTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/StructuredParserTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/linker/EntityLinkerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/linker/GuardLinkerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/linker/LinkersCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/linker/ModuleContainmentLinkerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/analyzer/linker/TopicLinkerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/FlowControllerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/GlobalExceptionHandlerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/GraphControllerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/IntelligenceControllerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/SafeFileReaderTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/TopologyControllerExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/TopologyControllerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/api/TopologyEndpointTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/benchmark/AnalysisBenchmarkTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cache/AnalysisCacheBatchReplaceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cache/AnalysisCacheConfidenceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cache/AnalysisCacheTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cache/CacheCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cache/FileHasherTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/AnalyzeCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/BundleCommandExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/BundleCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/CacheCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/CliExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/CodeIqCliTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/ConfigExplainSubcommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/ConfigValidateSubcommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/CypherCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/EnrichCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/FindCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/FlowCommandExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/FlowCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/GraphCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/IndexCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/PluginsCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/QueryCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/ServeCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/StatsCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/TopologyCommandExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/TopologyCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/cli/VersionCommandTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/CliStartupConfigOverridesTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/CodeIqConfigTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/CodeIqConfigTestSupport.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/CorsConfigTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/GraphBootstrapperTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/JacksonConfigTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/MapToJsonConverterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/ProjectConfigLoaderTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/UnifiedConfigAdapterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/UnifiedConfigBeansTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/security/BearerAuthFilterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/security/RateLimitFilterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/security/RequestIdFilterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/security/SecurityHeadersFilterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/security/ServingChainIntegrationTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/security/TokenResolverTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/CodeIqUnifiedConfigTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/ConfigDefaultsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/ConfigMergerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/ConfigResolverTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/ConfigValidatorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/EnvVarOverlayExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/EnvVarOverlayTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/config/unified/UnifiedConfigLoaderTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/deploy/AksLaunchScriptSentinelTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/AbstractAntlrDetectorHelperTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/AbstractRegexDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/AbstractStructuredDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/AntlrInfrastructureTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorContextResolvedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorContextTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorEmissionDefaultsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorInfoAnnotationTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorRegistryTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorResultTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorTestUtils.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/DetectorUtilsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/LanguageMappingTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/auth/AuthDetectorsCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/auth/CertificateAuthDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/auth/LdapAuthDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/auth/SessionHeaderAuthDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/csharp/CSharpDetectorsCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/csharp/CSharpDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/csharp/CSharpEfcoreDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/csharp/CSharpMinimalApisDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/csharp/CSharpStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/AngularComponentDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/FrontendDetectorsCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/FrontendDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/FrontendRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/ReactComponentDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/SvelteComponentDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/frontend/VueComponentDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/generic/GenericImportsDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/generic/GenericImportsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/go/GoDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/go/GoOrmDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/go/GoStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/go/GoWebDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/iac/BicepDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/iac/DockerfileDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/iac/IacDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/iac/TerraformDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/ActiveMqDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/AzureFunctionsDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/AzureMessagingDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/ClassHierarchyDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/ClassHierarchyDetectorResolvedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/ConfigDefDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/JavaDetectorsBranchCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/JavaDetectorsCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/JavaDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/JavaDetectorsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/JpaEntityDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/JpaEntityDetectorResolvedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/ModuleDepsDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/PublicApiDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/RepositoryDetectorResolvedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/SpringRestDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/SpringRestDetectorResolvedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/java/SpringSecurityDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/kotlin/KotlinStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/kotlin/KtorRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/jvm/scala/ScalaStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/markup/MarkdownStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/proto/ProtoStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/CeleryTaskDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/CeleryTaskDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/DjangoAuthDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/DjangoModelDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/DjangoModelDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/DjangoViewDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/FastAPIAuthDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/FastAPIAuthDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/FastAPIRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/FlaskRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/KafkaPythonDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/PydanticModelDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/PydanticModelDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/PythonStructuresDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/PythonStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/SQLAlchemyModelDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/python/SQLAlchemyModelDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/script/shell/BashDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/script/shell/PowerShellDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/sql/SqlMigrationDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/BatchStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/CloudFormationDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/ConfigDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/DockerComposeDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/GitHubActionsDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/GitLabCiDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/HelmChartDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/IniStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/JsonStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/KubernetesDetectorExpandedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/KubernetesDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/KubernetesRbacDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/OpenApiDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/PackageJsonDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/PropertiesDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/PyprojectTomlDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/SqlStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/TomlStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/TsconfigJsonDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/structured/YamlStructureDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/systems/cpp/CppStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/systems/rust/ActixWebDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/systems/rust/RustDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/systems/rust/RustStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/ExpressRouteDetectorExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/ExpressRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/FastifyRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/GraphQLResolverDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/KafkaJSDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/MongooseORMDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/NestJSControllerDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/NestJSGuardsDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/PassportJwtDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/PrismaORMDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/RemixRouteDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/SequelizeORMDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/TypeORMEntityDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/TypeScriptDetectorsExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/detector/typescript/TypeScriptStructuresDetectorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/e2e/E2EQualityTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/e2e/IntegrationSmokeTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/flow/CacheFlowDataSourceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/flow/FlowEngineExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/flow/FlowEngineTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/flow/FlowRendererTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/flow/FlowViewsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/graph/GraphStoreAggregateStatsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/graph/GraphStoreConfidenceRoundTripTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/graph/GraphStoreExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/graph/GraphStoreTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/graph/GraphStoreTopologyAndStatsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/health/GraphHealthIndicatorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/ArtifactManifestTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/FileInventoryTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/ProvenanceEdgeCasesTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/ProvenanceIntegrationTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/ProvenanceNeo4jRoundTripTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/ProvenanceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/RepositoryIdentityTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/evidence/EvidencePackAssemblerExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/evidence/EvidencePackAssemblerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/extractor/LanguageEnricherExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/extractor/LanguageEnricherTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/extractor/go/GoLanguageExtractorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/extractor/java/JavaLanguageExtractorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/extractor/python/PythonLanguageExtractorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/extractor/typescript/TypeScriptLanguageExtractorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/lexical/DocCommentExtractorTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/lexical/LexicalCrossLanguageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/lexical/LexicalEnricherTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/lexical/LexicalQueryServiceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/lexical/SnippetStoreTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/provenance/ArtifactMetadataProviderTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/provenance/ArtifactMetadataTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/query/CapabilityMatrixTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/query/QueryIntelligenceCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/query/QueryPlannerTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/ResolutionExceptionTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/ResolvedContractTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/ResolverRegistryTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/SymbolResolverContractTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/E2EResolverPetclinicTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaResolvedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSourceRootDiscoveryTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverAdversarialTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverConcurrencyTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverDeterminismTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverLayer1ExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverPathologicalTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverRandomizedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/intelligence/resolver/java/JavaSymbolResolverTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/mcp/McpToolsEvidenceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/mcp/McpToolsExpandedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/mcp/McpToolsTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/CodeEdgeConfidenceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/CodeNodeConfidenceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/CodeNodeEdgeExtendedTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/ConfidenceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/EdgeKindTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/KindConverterTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/ModelCoverageTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/model/NodeKindTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/query/QueryServiceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/query/StatsServiceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/query/TopologyServiceTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/web/SpaControllerConditionalTest.java delete mode 100644 src/test/java/io/github/randomcodespace/iq/web/SpaControllerMockMvcTest.java delete mode 100644 src/test/resources/application-test.yml delete mode 100644 src/test/resources/config-unified/full.yml delete mode 100644 src/test/resources/config-unified/malformed.yml delete mode 100644 src/test/resources/config-unified/minimal.yml delete mode 100644 src/test/resources/e2e/ground-truth-petclinic.json delete mode 100644 src/test/resources/e2e/ground-truth-realworld-express.json diff --git a/.github/workflows/beta-java.yml b/.github/workflows/beta-java.yml deleted file mode 100644 index 74214911..00000000 --- a/.github/workflows/beta-java.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Beta Release (Java) -on: - workflow_dispatch: # Manual trigger ONLY - -permissions: read-all - -jobs: - beta: - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2 - with: - fetch-depth: 0 - - - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v4.7.1 - with: - distribution: 'temurin' - java-version: '25' - cache: 'maven' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - - name: Determine beta version - id: version - run: | - LATEST_BETA=$(git tag -l 'v0.0.1-beta.*' | sort -V | tail -1) - if [ -z "$LATEST_BETA" ]; then - NEXT_NUM=0 - else - CURRENT_NUM=$(echo "$LATEST_BETA" | grep -oP 'beta\.\K[0-9]+') - NEXT_NUM=$((CURRENT_NUM + 1)) - fi - VERSION="0.0.1-beta.${NEXT_NUM}" - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "tag=v$VERSION" >> $GITHUB_OUTPUT - echo "Next beta version: $VERSION" - - - name: Set version in pom.xml - run: mvn versions:set -DnewVersion=${{ steps.version.outputs.version }} -B - - - name: Build and test - run: mvn clean verify -B - - - name: Deploy to Maven Central - env: - MAVEN_USERNAME: ${{ secrets.OSS_NEXUS_USER }} - MAVEN_PASSWORD: ${{ secrets.OSS_NEXUS_PASS }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - run: mvn deploy -P release -DskipTests -B - - - name: Create git tag - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git tag -a ${{ steps.version.outputs.tag }} -m "Beta release ${{ steps.version.outputs.version }}" - git push origin ${{ steps.version.outputs.tag }} - - - name: Create GitHub Release - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - with: - tag_name: ${{ steps.version.outputs.tag }} - name: "Beta ${{ steps.version.outputs.version }}" - prerelease: true - generate_release_notes: true - files: | - target/code-iq-*-cli.jar diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml deleted file mode 100644 index 523e6dcd..00000000 --- a/.github/workflows/ci-java.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Java CI - -# Lean Java CI — fast compile + unit-test gate on the Java reference side. -# Pairs with go-parity.yml: this workflow proves the Java jar still builds -# on every PR; go-parity.yml then uses the same build to diff against the -# Go port. -# -# Heavier checks (jacoco coverage, SpotBugs, OWASP dependency-check) live -# under workflow_dispatch via release-java.yml — they're not in the per-PR -# loop because they slow the Go port's PRs without adding signal. -# -# Disappears in Phase 6 cutover along with the rest of the Java tree. - -on: - push: - branches: [main] - pull_request: - branches: [main] - # NOTE: no `paths:` filter. The `build` job name is a required check - # on main's branch protection, and a `paths:` filter would cause the - # check to be skipped on PRs that don't touch Java — leaving the - # required check stuck at "Waiting for status to be reported", which - # blocks merge of every non-Java PR (e.g. PR #131 phase 5 release infra). - # Java compile is ~1 minute; the cost is worth the always-on signal - # until Phase 6 cutover deletes the Java tree entirely. - -permissions: read-all - -jobs: - build: - name: build - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2 - with: - fetch-depth: 0 - - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v4.7.1 - with: - distribution: 'temurin' - java-version: '25' - cache: 'maven' - - name: Compile + unit tests (skip frontend) - # -Dfrontend.skip=true so the npm step doesn't run — CI image - # doesn't carry node 20 by default and the frontend is owned by - # a separate workflow. -B (batch) + -ntp (no transfer progress) - # for quiet logs. - run: mvn -B -ntp -Dfrontend.skip=true verify - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4.6.2 - if: always() - with: - name: java-test-results - path: target/surefire-reports/ diff --git a/.github/workflows/go-parity.yml b/.github/workflows/go-parity.yml deleted file mode 100644 index 54f87666..00000000 --- a/.github/workflows/go-parity.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: go-parity - -# Java vs Go parity test for fixture-minimal. Validates that the Go port -# produces the same canonical graph shape as the Java reference until -# Phase 6 cutover deletes the Java tree. Runs on PRs that touch the Go -# tree, the Java tree, the parity harness, or this workflow. -# -# The Java side ships a JSON graph via `codeiq graph -f json` from the -# `serving` profile (Neo4j-backed). A small jq filter -# (go/parity/java-normalize.jq) rewrites that into the same per-file -# canonical shape that the Go-side parity.Normalize emits. The two -# normalized JSON blobs are then diff'd by the `parity` build tag in -# go/parity/parity_test.go, with expected-divergence.json holding the -# allow-list of intentional drift. - -on: - pull_request: - branches: [main] - paths: - - 'go/**' - - 'src/**' - - 'pom.xml' - - '.github/workflows/go-parity.yml' - workflow_dispatch: - -permissions: - contents: read - -jobs: - parity: - name: Java vs Go parity (fixture-minimal) - runs-on: ubuntu-latest - env: - CGO_ENABLED: "1" - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '25' - cache: maven - - uses: actions/setup-go@v5 - with: - # Pin to 1.25.x — 1.26+ isn't on enough developer machines yet. - go-version: '1.25.10' - cache: true - cache-dependency-path: go/go.sum - - name: Install C toolchain - run: sudo apt-get update -y && sudo apt-get install -y build-essential jq - - # ---- Java side ---------------------------------------------------- - - name: Build Java jar (skip frontend) - run: mvn -B -q -DskipTests -Dfrontend.skip=true package - - name: Stage Java fixture (separate copy so caches don't collide) - run: cp -r go/testdata/fixture-minimal /tmp/fm-java - - name: Java index → H2 cache - run: java -jar target/code-iq-*-cli.jar index /tmp/fm-java - - name: Java enrich → Neo4j (serving profile) - # `graph -f json` reads from Neo4j under the serving profile, not - # H2. Need to enrich first or the export prints "No graph data - # found. Run 'codeiq analyze' first." - run: | - java -Dspring.profiles.active=serving \ - -jar target/code-iq-*-cli.jar enrich /tmp/fm-java - - name: Java graph → normalized JSON - # Run from inside the fixture so Neo4j path resolution finds the - # store enrich wrote. java-normalize.jq pivots the Java - # {nodes:[...]} shape into the per-file array shape - # parity.Normalize uses on the Go side. - # - # The Java CLI prints Logback JSON log lines to stdout BEFORE the - # graph JSON, so we capture everything then awk to the first line - # that is exactly "{" — that's the pretty-printed graph object. - run: | - cd /tmp/fm-java - java -Dspring.profiles.active=serving \ - -jar "$GITHUB_WORKSPACE"/target/code-iq-*-cli.jar graph . -f json \ - > /tmp/java-raw-with-logs.json - awk '/^\{$/ {f=1} f' /tmp/java-raw-with-logs.json > /tmp/java-raw.json - jq -f "$GITHUB_WORKSPACE"/go/parity/java-normalize.jq /tmp/java-raw.json \ - > /tmp/java-normalized.json - - # ---- Go side ------------------------------------------------------ - - name: Build Go binary - working-directory: go - run: go build -o codeiq ./cmd/codeiq - - name: Go parity test (diff vs normalized Java output) - working-directory: go - env: - TEST_JAVA_NORMALIZED: /tmp/java-normalized.json - run: go test -tags=parity ./parity/... -v - - # ---- Failure artifact -------------------------------------------- - - name: Upload normalized JSON on failure - if: failure() - uses: actions/upload-artifact@v4 - with: - name: parity-diff - path: | - /tmp/java-normalized.json - /tmp/java-raw.json diff --git a/.github/workflows/release-java.yml b/.github/workflows/release-java.yml deleted file mode 100644 index d2c0b409..00000000 --- a/.github/workflows/release-java.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: Release to Maven Central -on: - workflow_dispatch: - inputs: - version: - description: 'Release version (e.g., 0.1.0)' - required: true - -permissions: read-all - -jobs: - release: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2 - - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v4.7.1 - with: - distribution: 'temurin' - java-version: '25' - cache: 'maven' - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} - gpg-passphrase: MAVEN_GPG_PASSPHRASE - - name: Configure git identity and non-interactive GPG for signed commit/tag - run: | - git config user.email "github-actions[bot]@users.noreply.github.com" - git config user.name "github-actions[bot]" - # Use the GPG key imported by setup-java (MAVEN_GPG_PRIVATE_KEY) for - # both commit and tag signing — same trust path as the artifact. - KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ {print $5; exit}') - if [ -z "$KEYID" ]; then - echo "no GPG secret key in agent — release-java.yml needs MAVEN_GPG_PRIVATE_KEY" >&2 - exit 1 - fi - git config user.signingkey "$KEYID" - git config gpg.format openpgp - git config commit.gpgsign true - git config tag.gpgsign true - # Reviewer finding cf64b44d (RAN-47, R5-1): - # `git commit -S` / `git tag -s` invoke gpg interactively by default - # and fail in non-interactive Actions shells when the imported key - # has a passphrase. setup-java only wires the passphrase for Maven - # signing (via MAVEN_GPG_PASSPHRASE in settings.xml); git itself - # has no equivalent autoconfig. Configure the gpg-agent for loopback - # pinentry, point gpg.program at a thin wrapper that injects - # --batch / --pinentry-mode loopback / --passphrase from - # MAVEN_GPG_PASSPHRASE, so signing succeeds non-interactively. - mkdir -p "$HOME/.gnupg" - chmod 700 "$HOME/.gnupg" - printf '%s\n' 'use-agent' 'pinentry-mode loopback' > "$HOME/.gnupg/gpg.conf" - printf '%s\n' 'allow-loopback-pinentry' > "$HOME/.gnupg/gpg-agent.conf" - gpgconf --kill gpg-agent || true - # Wrapper script: git invokes this with the same flags as gpg. - # We exec into gpg with --batch + loopback + the passphrase from - # the env (MAVEN_GPG_PASSPHRASE is set on each step that signs). - cat > "$HOME/.gnupg/gpg-loopback.sh" <<'WRAPPER' - #!/usr/bin/env bash - # Non-interactive gpg wrapper for `git commit -S` / `git tag -s`. - # MAVEN_GPG_PASSPHRASE is set on the workflow step that signs. - exec gpg --batch --yes --pinentry-mode loopback \ - --passphrase "${MAVEN_GPG_PASSPHRASE:-}" "$@" - WRAPPER - chmod +x "$HOME/.gnupg/gpg-loopback.sh" - git config gpg.program "$HOME/.gnupg/gpg-loopback.sh" - - name: Set release version and create signed release commit - env: - RELEASE_VERSION: ${{ inputs.version }} - # Picked up by the gpg-loopback wrapper script for `git commit -S`. - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - # Commit the version bump on a detached HEAD off the workflow's - # checkout. The commit is reachable only via the tag created below — - # no push to `main`, so this works under branch protection. - # The commit captures the exact source tree that the deploy step - # will build from, fixing the prior "tag diverges from released - # artifact" gap (Reviewer finding 47b718b9). - run: | - mvn -B -ntp versions:set -DnewVersion="$RELEASE_VERSION" -DgenerateBackupPoms=false - git add pom.xml - git commit -S -m "chore(release): ${RELEASE_VERSION}" - - name: Deploy to Maven Central - env: - MAVEN_USERNAME: ${{ secrets.OSS_NEXUS_USER }} - MAVEN_PASSWORD: ${{ secrets.OSS_NEXUS_PASS }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - run: mvn -B -ntp -P release clean deploy - - name: Create signed annotated tag and push - env: - RELEASE_VERSION: ${{ inputs.version }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} - # Annotated + GPG-signed tag pointing at the release commit (the - # current HEAD after the commit step above). Push only the tag — - # the release commit lives only as a tag-reachable object so we - # never need to update `main`, and branch protection stays clean. - run: | - git tag -s "v${RELEASE_VERSION}" -m "codeiq ${RELEASE_VERSION}" - git push origin "refs/tags/v${RELEASE_VERSION}" - - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - with: - tag_name: v${{ inputs.version }} - generate_release_notes: true - files: | - target/code-iq-*-cli.jar diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index a0d96850..d030363a 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -43,27 +43,14 @@ jobs: mv osv-scanner_linux_amd64 osv-scanner chmod +x osv-scanner ./osv-scanner --version - - name: Run osv-scanner (npm lockfile) - # Scoped to the npm lockfile by design: - # - # - osv-scanner v2's `transitivedependency/pomxml` plugin resolves - # Maven transitive deps via the `deps.dev` gRPC service. That - # service is intermittently `Unavailable` in GitHub-hosted CI - # (observed on PR #91 5th-pass), causing the scanner to exit - # non-zero even when zero vulnerabilities are found. - # - Maven coverage is already provided by Trivy (filesystem scan, - # this same workflow) plus Dependabot security updates against - # `pom.xml`. The OSV.dev advisory feed pulls from GHSA, which - # Dependabot also consumes — there is no SCA gap. - # - The npm lockfile is where osv-scanner adds unique value - # (deeper transitive resolution + ecosystem-specific advisories - # than Trivy provides for Node). - # - # AC §3 ("Zero High/Critical CVEs in dependency tree") is satisfied - # by the union of OSV-Scanner (npm) + Trivy (Maven, OS, container) - # + Dependabot (cross-ecosystem) — no single tool gates every - # ecosystem. - run: ./osv-scanner --lockfile=src/main/frontend/package-lock.json + - name: Run osv-scanner (Go module graph) + # Phase 6 cutover: project is Go-only. osv-scanner reads go.mod + # (the entire module graph including transitive deps) and emits + # any matching advisories from OSV.dev / GHSA. govulncheck (in + # go-ci.yml) is the call-graph-aware companion that filters to + # *reachable* vulns — keeping both gives both "have we got it" + # AND "are we exposed". + run: ./osv-scanner --lockfile=go/go.mod trivy: name: Trivy (filesystem + container scan) @@ -97,13 +84,16 @@ jobs: # — setup-python@v6 ships a current vendored pip, and the Scorecard # rule fires only on user-installed packages. run: python -m pip install --quiet 'semgrep==1.161.0' - - name: Run semgrep (security-audit + owasp-top-ten + java) + - name: Run semgrep (security-audit + owasp-top-ten + golang) + # Phase 6 cutover: project is Go-only. p/java replaced with + # p/golang. p/security-audit + p/owasp-top-ten stay (both + # language-agnostic rule sets). run: | semgrep scan \ --error \ --config p/security-audit \ --config p/owasp-top-ten \ - --config p/java \ + --config p/golang \ --severity ERROR \ --metrics off @@ -145,52 +135,32 @@ jobs: with: node-version: '20' - run: | - # Scope jscpd to production code only: - # - src/main/java — Java production code - # - src/main/frontend/src — React/TS production code - # Tests (Java unit/integration, TS unit, Playwright e2e specs) - # share fixture/assertion shape by design — that parallelism is a - # feature for catching contract regressions, not a refactoring - # target. Scanning ./ as the AC originally proposed produces - # ~12.83% duplication driven by *.spec.ts e2e parallelism + - # *LanguageExtractorTest.java parallel-shape tests; both are - # intentional. AC §3 wording "duplication < 3% on new code" — - # interpreting "new code" as production code, gated per-PR via - # this scoped scan. + # Scope jscpd to Go production code only: + # - go/cmd — main entry point + # - go/internal — production code (100 detectors + pipeline + MCP) + # Tests share fixture/assertion shape by design (parallelism for + # catching contract regressions, not a refactoring target). # - # `*LanguageExtractor.java` files (one per language under - # intelligence/extractor/{java,typescript,python,go}) implement - # the same template-method shape against per-language ASTs by - # design — collapsing them into a base class would couple - # unrelated grammars and erase the per-language readability that - # makes them reviewable. Excluded from jscpd; cleanup-via-base-class - # is a separate board call, not a CI gate. - # `--min-tokens 200` is calibrated to Java's verbosity floor. - # A 97-detector codebase has, by definition, 97 file headers - # consisting of `package` + 8–15 imports + `@Component public class` - # + interface-implementation scaffold + a few constants — that's - # 150–180 tokens of identical structural boilerplate per file, with - # zero refactor surface (the imports differ by detector concern, - # the type names differ by node kind, but the *shape* is shared - # template-method conformance). At the jscpd default of 50, those - # headers produce ~400 trivial clones; at 100 they still produce - # ~130. 200 tokens roughly corresponds to a meaningful method body - # or a non-trivial code block — i.e. real duplicate logic, not - # language scaffolding. Threshold (3%) and the production-only - # scope are unchanged. + # `*language_extractor.go` (one per language under + # intelligence/extractor/{java,typescript,python,golang}) and + # `structures.go` (kotlin/scala/cpp/rust) implement the same + # template-method shape against per-language ASTs by design; + # collapsing into a base would couple unrelated grammars and + # erase per-language readability. Excluded. # - # `*StructuresDetector.java` (Kotlin/Scala/Cpp/Rust) implement the - # same template-method shape against per-language ASTs by design, - # same as the LanguageExtractors above. Excluded for the same - # reason — collapsing into a base class would couple unrelated - # grammars and obscure per-language readability. + # --min-tokens 200 calibrated to Go's verbosity floor: each + # detector file's package decl + imports + Type/init/Name/ + # SupportedLanguages/DefaultConfidence/Detect scaffold is + # ~150-180 tokens of identical structural boilerplate across + # 100 detectors. 200 tokens is the floor for "real duplicate + # logic" rather than language scaffolding. npx --yes jscpd@4 \ --threshold 3 \ --min-tokens 200 \ --reporters consoleFull \ - --format "java,javascript,typescript" \ - --ignore "**/target/**,**/node_modules/**,**/grammar/**,**/generated-sources/**,**/dist/**,**/build/**,**/coverage/**,**/intelligence/extractor/**/*LanguageExtractor.java,**/detector/**/*StructuresDetector.java" \ - src/main/java src/main/frontend/src + --format "go" \ + --ignore "**/vendor/**,**/testdata/**,**/grammar/**,**/generated/**,**/dist/**,**/coverage/**,**/intelligence/extractor/**/language_extractor.go,**/detector/**/structures.go" \ + go/cmd go/internal sbom: name: SBOM (SPDX + CycloneDX) diff --git a/.gitignore b/.gitignore index 752155b1..ced6b991 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,12 @@ -# Java build -target/ -*.class -*.jar -!src/main/resources/static/js/vendor/*.js -.classpath -.project -.settings/ -.factorypath -*.iml +# Go build +go/codeiq +go/dist/ + +# Go test artifacts +*.test +*.out +coverage.out +coverage.html # IDE .idea/ @@ -23,20 +22,23 @@ target/ .DS_Store Thumbs.db -# Project runtime data +# Project runtime data — the embedded Kuzu graph + SQLite analysis cache +# both land under .codeiq/ when codeiq runs against a target repo. Never +# commit either; they're per-repo and per-machine. .codeiq/ *.db *.db-wal *.db-shm -*.mv.db +# Stray Kuzu temp files +*.wal +*.kuzu-tmp # Environment & secrets # Broad .env* glob catches .env, .env.local, .env.prod, .env.test, .env.* — all -# variants. Pre-PR-3 we only excluded the first two and several .env. -# variants would have committed silently. +# variants. .env .env.* -# Java keystores & PKCS#12 archives — high-value secrets that have shown up in +# Keystores / PKCS#12 archives — high-value secrets that have shown up in # audits; never commit, even encrypted. *.jks *.p12 @@ -63,27 +65,12 @@ secrets.yaml # Logs *.log -# Frontend -src/main/frontend/node_modules/ -src/main/frontend/node/ -src/main/frontend/dist/ -src/main/frontend/tsconfig.tsbuildinfo -playwright-report/ -test-results/ -# Generated explorer CSS (rebuild via: cd src/main/frontend && npm run build:explorer-css) -src/main/resources/static/css/explorer.css -# Frontend build output copied into Spring static resources -src/main/resources/static/index.html -src/main/resources/static/assets/CodeGraphView-*.js -src/main/resources/static/assets/index-*.js -src/main/resources/static/assets/index-*.css -src/main/resources/static/assets/vendor-*.js - -# Distribution +# Distribution / release artifacts *.tar.gz *.zip +dist/ -# Python (legacy — removed from project) +# Python tooling that codeiq sometimes shells out to (linters, etc.) __pycache__/ *.py[cod] *.egg-info/ @@ -93,8 +80,6 @@ __pycache__/ .pytest_cache/ pytest-of-*/ htmlcov/ -dist/ -build/ *.whl pyproject.toml !go/testdata/**/pyproject.toml @@ -107,14 +92,12 @@ venv/ docs/superpowers/* !docs/superpowers/baselines/ -# Docker & Helm (bundled separately) +# Docker & Helm (bundled separately by the release flow if/when needed) Dockerfile docker-compose.yml helm/ -# Neo4j embedded data -neo4j-data/ -graph.db/ +# Worktrees .worktrees/ # Phase A baseline @@ -122,5 +105,6 @@ graph.db/ docs/superpowers/baselines/**/raw/** # Agent-generated plans / scratch (not project deliverables) -go-port-phase4-plan.md phase*-plan.md +*-plan.md +!docs/superpowers/plans/*.md diff --git a/CHANGELOG.md b/CHANGELOG.md index af1bd15d..b7980b50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,49 @@ for that specific tag for the per-commit details. ## [Unreleased] +## [v1.0.0] - 2026-05-13 + +### Changed + +- **Phase 6 cutover — Java reference deleted, Go is the only + implementation.** Single static binary released from `go/cmd/codeiq`. + Deletes `src/`, `pom.xml`, `spotbugs-exclude.xml`, + `.github/workflows/{ci-java,beta-java,release-java,go-parity}.yml`. + ~8.9 MB / ~1500 files removed. + +### v1.0.0 surface + +What ships in v1.0.0 (carrying forward from the c363727 squash + c630245 release infra): + +- 100 detectors across 35+ languages. +- Deterministic graph with confidence-aware NodeMerger and canonical + `(src, tgt, kind)` edge dedup; phantom-drop visibility. +- 6 consolidated mode-driven MCP tools + `run_cypher` escape hatch + + `review_changes`. The deprecated 34 narrow tools remain wired for + back-compat in this release; targeted for removal in v1.1.0. +- `codeiq review` CLI + `review_changes` MCP tool with Ollama (local + or Cloud) for LLM-driven PR review against graph evidence. +- Goreleaser cross-platform binaries (linux/amd64, linux/arm64, + darwin/arm64), SPDX SBOMs, Cosign keyless signatures via GitHub + OIDC + Sigstore Rekor. +- Optional Homebrew tap publish (`RandomCodeSpace/homebrew-codeiq`). +- Per-PR perf-regression gate (`perf-gate.yml`). + +### Removed + +- `src/main/java/`, `src/test/java/`, `src/main/frontend/`, + `src/main/resources/`, `pom.xml`, `spotbugs-exclude.xml`. +- `.github/workflows/ci-java.yml`, `release-java.yml`, `beta-java.yml`, + `go-parity.yml` (the last needed the Java jar build that's gone). + +### Migration notes + +Pre-cutover Java-side history is preserved in the squash-merge commit +`c363727` and on `origin/main`. Anyone needing to recover Java files +can `git show c363727:` or `git checkout c363727 -- `. + +[v1.0.0]: https://github.com/RandomCodeSpace/codeiq/releases/tag/v1.0.0 + ### Added - **Phase 5 release infrastructure for the Go binary** — diff --git a/CLAUDE.md b/CLAUDE.md index 484e2ac8..29c00150 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,498 +1,440 @@ -# codeiq (Java) -- Project Instructions +# codeiq (Go) — Project Instructions ## What This Project Is -**codeiq** -- a CLI tool + server that scans codebases to build a deterministic code knowledge graph. No AI, no external APIs -- pure static analysis. 99 detectors, 35+ languages, Neo4j Embedded graph database, Spring AI MCP server, REST API, web UI. +**codeiq** — a CLI tool + MCP server that scans codebases to build a +deterministic code knowledge graph. No AI, no external APIs — pure +static analysis. 100 detectors, 35+ languages, Kuzu embedded graph +database, MCP stdio server, single static Go binary. -- **Maven coordinates:** `io.github.randomcodespace.iq:code-iq` (artifactId intentionally unchanged) -- **CLI command:** `codeiq` (via `java -jar`; JAR filename remains `code-iq-*-cli.jar`) -- **Java package:** `io.github.randomcodespace.iq` (under `src/main/java/`) -- **GitHub repo:** `RandomCodeSpace/codeiq` (branch: `main`) -- **Cache directory on disk:** `.codeiq/cache` (H2 analysis cache) -- **Neo4j directory on disk:** `.codeiq/graph/graph.db` (enriched graph) -- **Config file:** `codeiq.yml` (project-level overrides) +- **CLI command**: `codeiq` (single binary from `go/cmd/codeiq/main.go`) +- **Go module**: `github.com/randomcodespace/codeiq/go` +- **Go directive**: `go 1.25.0` (dep-mandated by `modelcontextprotocol/go-sdk`); `toolchain go1.25.10` +- **GitHub repo**: `RandomCodeSpace/codeiq` (default branch: `main`) +- **Cache on disk**: `.codeiq/cache/codeiq.sqlite` (SQLite analysis cache) +- **Graph on disk**: `.codeiq/graph/codeiq.kuzu` (Kuzu embedded graph) +- **Config file**: `codeiq.yml` (project-level overrides) + +The Java/Spring Boot reference that seeded this codebase was deleted +in Phase 6 cutover (v1.0.0). For history, see commits `c363727` (port +landing) and `c630245` (release infra). ## Tech Stack -> **Source of truth:** `pom.xml` and `src/main/frontend/package.json`. Update -> these pins together — when `pom.xml` bumps, this list moves with it as part -> of the same PR. Pre-PR-5 the list had drifted (Spring Boot 4.0.5, -> Neo4j 2026.02.3, Spring AI 2.0.0-M3); PR 5 brought it back in sync. - -- Java 25 (virtual threads, pattern matching, records, sealed classes) -- Spring Boot 4.0.6 (parent POM ``) -- Neo4j Embedded 2026.04.0 (Community Edition, no external server) -- Spring AI 2.0.0-M4 (MCP server, `@McpTool` annotations, streamable HTTP) -- Bucket4j 8.18.0 (`bucket4j_jdk17-core`, in-process token-bucket rate limiter) -- logstash-logback-encoder 9.0 (JSON-structured logging in `serving` profile) -- micrometer-registry-prometheus (`/actuator/prometheus`, version managed by Boot BOM) -- JavaParser 3.28.0 (Java AST analysis) -- ANTLR 4.13.2 (TypeScript/JavaScript, Python, Go, C#, Rust, C++ grammars) -- Picocli 4.7.7 (CLI framework, integrated with Spring Boot) -- React 18 + TypeScript + Vite 6 + Ant Design v5 + ECharts v5 (web UI) -- H2 (incremental analysis cache) +> Source of truth: `go/go.mod` + `go/go.sum`. Update pins there; this +> list moves with them in the same commit. + +- **Go 1.25.10** — toolchain pin; module min is 1.25.0 (clamped by the + MCP SDK's own `go` directive). +- **Kuzu 0.7.1** (`github.com/kuzudb/go-kuzu`) — embedded graph DB. + CGO. v0.7.1 quirks documented in `## Gotchas` below. +- **`mattn/go-sqlite3` 1.14.22** — SQLite analysis cache. CGO. +- **`smacker/go-tree-sitter`** — AST parsing for Java / Python / + TypeScript / Go. +- **`modelcontextprotocol/go-sdk` v1.6** — stdio MCP server. v1.6 API + shape: `Server.Serve(ctx, mcpsdk.Transport)`; no `NewStdioTransport` + helper. +- **`spf13/cobra`** — CLI framework. Subcommand registration via + `internal/cli` blank imports. +- **`golang-jwt/jwt/v5`** — token validation surface (kept from a + serve-mode prototype; serve isn't fully ported yet). ## Architecture -### Deployment Model +### Pipeline ``` -Developer machine: - codeiq index /repo → H2 cache (.codeiq/cache/) - codeiq enrich /repo → Neo4j (.codeiq/graph/graph.db) - codeiq bundle /repo → bundle.zip (graph + source snapshot) - -Remote server (or local): - codeiq serve /repo → read-only API + MCP + UI (from Neo4j) +index: FileDiscovery → Parsers → Detectors (goroutine pool) → GraphBuilder → SQLite cache +enrich: SQLite → Linkers → LayerClassifier → LexicalEnricher → LanguageEnricher → ServiceDetector → Kuzu (COPY FROM) +serve: (deferred — not ported in v1.0.0) +mcp: Kuzu → QueryService → 6 consolidated MCP tools + run_cypher escape hatch + review_changes ``` -**Key principle:** MCP and API are strictly **read-only**. No data manipulation from the serving layer. Analysis happens only via CLI (`index`/`enrich`). The remote server may not have source code access (bundle deployment model). - -### Pipeline +### Pipeline components + +- **`internal/analyzer/file_discovery.go`** — `git ls-files` first, + dir-walk fallback. Maps extension → `parser.Language` via + `LanguageFromExtension` in `internal/parser/parser.go`. +- **`internal/parser`** — tree-sitter wrappers + a structured parser + for YAML/JSON/TOML/INI/properties. Falls back to regex-only when + parse fails (matches Java's per-file try/catch). +- **`internal/detector`** — `@Component` analogue is Go's `init()` + blank-import pattern; every detector registers itself with + `detector.Default`. Auto-discovery via `internal/cli/detectors_register.go` + (this file is the choke point — every detector package leaf must + blank-import here or the binary won't fire it). +- **`internal/analyzer/graph_builder.go`** — buffers detector results. + Confidence-aware node merge (`mergeNode`), canonical + `(source, target, kind)` edge dedup, deterministic Snapshot with + dangling-edge drop. Surfaces dedup/drop counts on `Stats`. +- **`internal/analyzer/linker/`** — TopicLinker, EntityLinker, + ModuleContainmentLinker. Each emits `Result{Nodes, Edges}` that's + `.Sorted()` at the call site (Phase 1 §1.4). +- **`internal/graph`** — Kuzu wrapper. Read-only via `OpenReadOnly` + (mutation gate in `cypher.go`). +- **`internal/mcp`** — 6 consolidated mode-driven tools (`graph_summary`, + `find_in_graph`, `inspect_node`, `trace_relationships`, + `analyze_impact`, `topology_view`), `run_cypher` escape hatch, the + 34 deprecated narrow tools, plus `review_changes`. +- **`internal/review`** — diff parser, Ollama-compatible chat client, + ReviewService orchestrator. Default endpoint = local Ollama; + `OLLAMA_API_KEY` flips to Ollama Cloud. + +### Package layout ``` -index: FileDiscovery → Parsers → Detectors (virtual threads) → GraphBuilder → H2 cache -enrich: H2 → Linkers → LayerClassifier → LexicalEnricher → LanguageEnricher → ServiceDetector → Neo4j (UNWIND bulk-load) -serve: Neo4j → GraphStore → QueryService → REST API / MCP / Web UI +go/ +├── cmd/codeiq/ # main package — single binary entrypoint +├── internal/ +│ ├── analyzer/ # pipeline orchestration +│ │ └── linker/ # cross-file enrichers +│ ├── buildinfo/ # version/commit/date from -ldflags +│ ├── cache/ # SQLite analysis cache +│ ├── cli/ # cobra subcommands + detector registrations +│ ├── detector/ # 100 detectors organized by category +│ │ ├── auth/ +│ │ ├── base/ # AbstractDetector analogues + helpers +│ │ ├── csharp/ +│ │ ├── frontend/ # React, Vue, Svelte, Angular, frontend routes +│ │ ├── generic/ +│ │ ├── golang/ +│ │ ├── iac/ # Terraform, Bicep, Dockerfile, CloudFormation +│ │ ├── jvm/ +│ │ │ ├── java/ # ~37 Java detectors +│ │ │ ├── kotlin/ +│ │ │ └── scala/ +│ │ ├── markup/ # Markdown +│ │ ├── proto/ +│ │ ├── python/ +│ │ ├── script/shell/ # PowerShell, Bash +│ │ ├── sql/ # SqlMigration +│ │ ├── structured/ # YAML, JSON, TOML, K8s, Helm, OpenAPI, … +│ │ ├── systems/{cpp,rust}/ +│ │ └── typescript/ +│ ├── flow/ # architecture-flow diagram engine +│ ├── graph/ # Kuzu facade +│ ├── intelligence/ # Lexical + language extractors + evidence + query planner +│ ├── mcp/ # MCP server + tool definitions +│ ├── model/ # CodeNode, CodeEdge, NodeKind, EdgeKind, Confidence, Layer +│ ├── parser/ # tree-sitter + structured parsers +│ ├── query/ # service / topology / stats +│ └── review/ # PR-review pipeline (diff + LLM) +├── parity/ # parity harness (build tag `parity`) +├── testdata/ # fixtures +├── go.mod +└── go.sum ``` -### Pipeline Components -- **FileDiscovery** -- discovers files via `git ls-files` or directory walk, maps extensions to languages -- **StructuredParser** -- routes files to JavaParser (Java), ANTLR (TS/Py/Go/C#/Rust/C++), or raw text -- **Detectors** -- 97 concrete detector beans (Spring `@Component`), auto-discovered via classpath scan -- **GraphBuilder** -- buffers all nodes and edges, flushes nodes first then edges (determinism guarantee) -- **Linkers** -- run after all detectors: `TopicLinker`, `EntityLinker`, `ModuleContainmentLinker` -- **LayerClassifier** -- sets `layer` property on every node using node kind, framework, and path heuristics -- **ServiceDetector** -- scans filesystem for build files (30+ build systems), creates SERVICE nodes with CONTAINS edges -- **GraphStore** -- facade over Neo4j, UNWIND-based bulk save, Cypher reads (no SDN for reads) -- **AnalysisCache** -- H2-backed file hash cache for incremental analysis +## Critical Rules -### Spring Profiles -- **`indexing`** -- active during CLI index/analyze/stats/graph/query/find/flow/bundle/cache/plugins commands. No Neo4j. -- **`serving`** -- active during `serve` command. Starts Neo4j Embedded, REST API, MCP server, web UI. +### Read-Only MCP -## Package Structure +The MCP server is **strictly read-only** — no data mutation from tool +calls. `run_cypher` rejects mutation keywords at the gate +(`internal/graph/cypher.go`). `review_changes` reads the graph and +shells out to `git`; it never writes to `.codeiq/`. -``` -io.github.randomcodespace.iq - |-- CodeIqApplication.java # Spring Boot main class - |-- analyzer/ # Pipeline: Analyzer, FileDiscovery, GraphBuilder, LayerClassifier, ServiceDetector - | |-- linker/ # Cross-file linkers: TopicLinker, EntityLinker, ModuleContainmentLinker - |-- api/ # REST controllers: GraphController (read-only), FlowController, TopologyController - |-- cache/ # AnalysisCache (H2), FileHasher - |-- cli/ # Picocli commands: index, enrich, serve, analyze, stats, etc. - |-- config/ # Spring config: Neo4jConfig, CodeIqConfig, JacksonConfig - |-- detector/ # Detector interface + 97 concrete detectors - | |-- auth/ # LDAP, certificate, session/header auth (cross-cutting) - | |-- csharp/ # EF Core, Minimal APIs, C# structures - | |-- frontend/ # React, Vue, Angular, Svelte, frontend routes - | |-- generic/ # Generic imports - | |-- go/ # Go web, ORM, structures - | |-- iac/ # Terraform, Dockerfile, Bicep - | |-- jvm/ # JVM-family languages - | | |-- java/ # 27 Java detectors (Spring, JPA, Kafka, gRPC, etc.) - | | |-- kotlin/ # Ktor, Kotlin structures - | | |-- scala/ # Scala structures - | |-- markup/ # Markdown structure (renamed from docs/) - | |-- proto/ # Proto structures - | |-- python/ # Django, FastAPI, Flask, SQLAlchemy, Celery, etc. - | |-- script/ # Scripting languages - | | |-- shell/ # Bash, PowerShell - | |-- sql/ # (placeholder — follow-up #48) - | |-- structured/ # YAML, JSON, TOML, INI, properties, K8s, Helm, GHA, etc. (renamed from config/) - | |-- systems/ # Systems languages - | | |-- cpp/ # C++ structures - | | |-- rust/ # Actix-web, Rust structures - | |-- typescript/ # Express, NestJS, Fastify, Prisma, TypeORM, etc. - |-- flow/ # FlowEngine, FlowRenderer, FlowViews, FlowModels - |-- grammar/ # ANTLR parser factory + generated parsers - |-- graph/ # GraphStore (Neo4j facade), GraphRepository (SDN, writes only) - |-- health/ # GraphHealthIndicator (Spring Actuator) - |-- mcp/ # McpTools (34 @McpTool methods, read-only, includes intelligence tools) - |-- model/ # CodeNode, CodeEdge, NodeKind (34), EdgeKind (28), Confidence - |-- intelligence/ # Intelligence enrichment (Phase 2-5) - | |-- lexical/ # LexicalEnricher, LexicalQueryService, DocCommentExtractor, SnippetStore - | |-- extractor/ # LanguageEnricher, LanguageExtractor, LanguageExtractionResult - | | |-- java/ # JavaLanguageExtractor - | | |-- typescript/ # TypeScriptLanguageExtractor - | | |-- python/ # PythonLanguageExtractor - | | |-- go/ # GoLanguageExtractor - | |-- evidence/ # EvidencePack, EvidencePackAssembler - | |-- query/ # QueryPlanner, QueryRoute, QueryPlan - |-- query/ # QueryService, StatsService (categorized), TopologyService - |-- web/ # Static resource serving (React SPA) -``` +Analysis/enrichment happens only via the CLI commands `index` / +`enrich`. -## Critical Rules +### Determinism + +- Same input MUST produce same output. Every run. +- No `map` iteration without sorting first (every range loop over a + map sorts keys before emit). +- `GraphBuilder.Snapshot` sorts nodes + edges by ID. +- Linker outputs go through `Result.Sorted()` at the boundary. +- All detectors are stateless — no mutable struct fields. Stateless + methods only. The single shared instance per detector type is + registered with `detector.Default` at package init. + +### Detector dispatch is choke-pointed -### Read-Only Serving Layer -- MCP and API are **strictly read-only** -- no data manipulation -- Analysis/enrichment happens only via CLI (`index`, `enrich`) -- Remote servers may not have source code access (bundle deployment) -- No `POST /api/analyze` or `analyze_codebase` MCP tool - -### Determinism is Non-Negotiable -- Same input MUST produce same output, every time -- No `Set` iteration without sorting first (`TreeSet` or `stream().sorted()`) -- No dependency on thread completion order (GraphBuilder uses indexed result slots) -- All detectors must be stateless -- no mutable instance fields, use method-local state only - -### Generic Detection -- Not Example-Specific -- Every feature must work for ALL languages and architectures, not just the example given -- Framework detectors must have discriminator guards (e.g., Quarkus detector requires `io.quarkus` import) -- ServiceDetector supports 30+ build systems across all ecosystems, not just Maven -- Never fix for one language and forget others - -### Virtual Thread Safety -- All file I/O and Neo4j operations run on virtual threads -- The H2 analysis cache uses `synchronized` blocks for thread safety -- Detectors MUST be stateless -- Spring `@Component` beans are singletons +Adding a new detector package under `internal/detector//` is NOT +enough. The package must be blank-imported in +[`internal/cli/detectors_register.go`](go/internal/cli/detectors_register.go). +Without that line, the package's `init()` never runs and the binary +ships without your detector. The Phase 4 benchmark exposed this bug +when 15 language families silently produced 0 nodes — see commit +`04098be` for the fix. + +### Goroutine safety + +- File I/O and SQLite writes run on a bounded worker pool + (`Analyzer.opts.Workers`, default 2× GOMAXPROCS). +- Detectors must be stateless. Method-local state only. +- Kuzu reads use the embedded API; one query at a time per + `Store.Cypher` call. The store internal mutex serializes. ## CLI Commands -| Command | Description | -|---------|-------------| -| `index [path]` | Memory-efficient batched scanning to H2 (preferred for large codebases) | -| `enrich [path]` | Load H2 into Neo4j, run linkers, classify layers, detect services | -| `serve [path]` | Start read-only web UI + REST API + MCP server (requires enrich first) | -| `analyze [path]` | Legacy in-memory scan (use index+enrich for large codebases) | -| `stats [path]` | Show rich categorized statistics from analyzed graph | -| `graph [path]` | Export graph (JSON, YAML, Mermaid, DOT) | -| `query [path]` | Query graph relationships (consumers, producers, callers) | -| `find [what] [path]` | Preset queries (endpoints, guards, entities, topics, etc.) | -| `cypher [query]` | Execute raw Cypher queries against Neo4j | -| `flow [path]` | Generate architecture flow diagrams | -| `bundle [path]` | Package graph + source into distributable ZIP | -| `cache [action]` | Manage analysis cache | -| `plugins [action]` | List and inspect detectors | -| `topology [path]` | Show service topology map | -| `version` | Show version info | - -### Standard Pipeline +| Command | Purpose | +|---|---| +| `index [path]` | Scan files → SQLite analysis cache. | +| `enrich [path]` | Load cache → Kuzu graph; run linkers + LayerClassifier + intelligence. | +| `mcp [path]` | Stdio MCP server (Claude / Cursor). | +| `stats [path]` | Categorized statistics from the enriched graph. | +| `query [path]` | consumers/producers/callers/dependencies/dependents/shortest-path/cycles/dead-code. | +| `find [path]` | endpoints, entities, services, … | +| `cypher [path]` | Raw Cypher (read-only) against Kuzu. | +| `flow [path]` | Architecture-flow diagrams (mermaid/dot/yaml). | +| `graph [path]` | Export graph in json / yaml / mermaid / dot. | +| `topology [path]` | Service-topology projection. | +| `review [path]` | LLM-driven PR review (Ollama by default). | +| `cache ` | Inspect / clear the SQLite cache. | +| `plugins ` | List + describe registered detectors. | +| `config ` | Validate / explain `codeiq.yml`. | +| `version` | `--version` long form. | + +### Standard pipeline ```bash -# For large codebases (44K+ files): -codeiq index /path/to/repo # ~220s for 44K files, writes to H2 -codeiq enrich /path/to/repo # loads H2 → Neo4j with linkers/layers/services -codeiq serve /path/to/repo # read-only server - -# For small codebases: -codeiq analyze /path/to/repo # in-memory, all-in-one -codeiq serve /path/to/repo # needs enrich if using index +codeiq index /path/to/repo +codeiq enrich /path/to/repo +codeiq stats /path/to/repo +codeiq mcp /path/to/repo # for Claude / Cursor wiring ``` -## Server Endpoints (all read-only) - -### REST API (`/api`) -- 37 endpoints - -**GraphController** (`/api`): -- `GET /api/stats` -- Rich categorized statistics (graph, languages, frameworks, infra, connections, auth, architecture) -- `GET /api/stats/detailed?category=` -- Single category stats -- `GET /api/kinds` -- Node kinds with counts -- `GET /api/kinds/{kind}` -- Paginated nodes by kind -- `GET /api/nodes` -- Paginated node queries -- `GET /api/nodes/{id}/detail` -- Full node detail with edges -- `GET /api/nodes/{id}/neighbors` -- Neighbor traversal -- `GET /api/edges` -- Paginated edge queries -- `GET /api/ego/{center}` -- Ego subgraph -- `GET /api/query/cycles` -- Cycle detection -- `GET /api/query/shortest-path` -- Shortest path between nodes -- `GET /api/query/consumers/{id}`, `/producers/{id}`, `/callers/{id}`, `/dependencies/{id}`, `/dependents/{id}` -- `GET /api/query/dead-code` -- Dead code detection (semantic edge filtering, excludes entry points) -- `GET /api/triage/component?file=` -- Agentic triage by file -- `GET /api/triage/impact/{id}` -- Impact trace -- `GET /api/search?q=` -- Free-text search -- `GET /api/file?path=` -- Source files (path traversal protected) - -**TopologyController** (`/api/topology`): -- `GET /api/topology` -- Service topology map -- `GET /api/topology/services/{name}` -- Service detail -- `GET /api/topology/services/{name}/deps` -- Service dependencies -- `GET /api/topology/services/{name}/dependents` -- Service dependents -- `GET /api/topology/blast-radius/{nodeId}` -- Blast radius analysis -- `GET /api/topology/path` -- Find path between services -- `GET /api/topology/bottlenecks` -- Find bottleneck services -- `GET /api/topology/circular` -- Circular dependency detection -- `GET /api/topology/dead` -- Dead service detection - -**FlowController** (`/api/flow`): -- `GET /api/flow` -- List available flow views -- `GET /api/flow/{view}` -- Flow diagram for specific view -- `GET /api/flow/{view}/{nodeId}/children` -- Node children in flow -- `GET /api/flow/{view}/{nodeId}/parent` -- Node parent in flow - -**IntelligenceController** (`/api/intelligence`): -- `GET /api/intelligence/evidence` -- Evidence pack for a node -- `GET /api/intelligence/manifest` -- Artifact manifest -- `GET /api/intelligence/capabilities` -- Capability matrix - -### MCP Tools (34, via `@McpTool` annotation) -`get_stats`, `get_detailed_stats`, `query_nodes`, `query_edges`, `get_node_neighbors`, `get_ego_graph`, `find_cycles`, `find_shortest_path`, `find_consumers`, `find_producers`, `find_callers`, `find_dependencies`, `find_dependents`, `find_dead_code`, `generate_flow`, `run_cypher`, `find_component_by_file`, `trace_impact`, `find_related_endpoints`, `search_graph`, `read_file`, `get_topology`, `service_detail`, `service_dependencies`, `service_dependents`, `blast_radius`, `find_path`, `find_bottlenecks`, `find_circular_deps`, `find_dead_services`, `find_node`, `get_evidence_pack`, `get_artifact_metadata`, `get_capabilities` +## MCP Tools + +The MCP server registers 6 consolidated mode-driven tools + `run_cypher` ++ `review_changes`. The 34 narrow tools from the Java side stay wired +for one release (v1.0.x) for back-compat with agents pinned to old +names; they'll be removed in v1.1.0. + +| Consolidated tool | mode dispatch | +|---|---| +| `graph_summary` | `overview` / `categories` / `capabilities` / `provenance` | +| `find_in_graph` | `nodes` / `edges` / `text` / `fuzzy` / `by_file` / `by_endpoint` | +| `inspect_node` | `neighbors` / `ego` / `evidence` / `source` | +| `trace_relationships` | `callers` / `consumers` / `producers` / `dependencies` / `dependents` / `shortest_path` | +| `analyze_impact` | `blast_radius` / `trace` / `cycles` / `circular_deps` / `dead_code` / `dead_services` / `bottlenecks` | +| `topology_view` | `summary` / `service` / `service_deps` / `service_dependents` / `flow` | +| `run_cypher` | (escape hatch — mutation-rejected) | +| `review_changes` | (Ollama-driven PR review) | ## Adding a New Detector -1. Create file in `detector//MyDetector.java` -2. Implement the `Detector` interface: - ```java - @Component - public class MyDetector implements Detector { - @Override public String getName() { return "my_detector"; } - @Override public Set getSupportedLanguages() { return Set.of("java"); } - @Override public DetectorResult detect(DetectorContext ctx) { - DetectorResult result = new DetectorResult(); - // Your detection logic here - return result; - } - } - ``` -3. **No registry changes needed** -- auto-discovered via Spring classpath scan -4. **Framework-specific detectors MUST have discriminator guards** -- require framework-specific imports before detecting (e.g., Quarkus requires `io.quarkus`, Fastify requires `fastify` import) -5. For Java files needing AST access, extend `AbstractJavaParserDetector` -6. For multi-language support via ANTLR, extend `AbstractAntlrDetector` -7. For regex-only detection, extend `AbstractRegexDetector` -8. Create test in `src/test/java/.../detector//MyDetectorTest.java` -9. Include a determinism test (run twice, assert identical output) -10. Run `mvn test` -- all tests must pass - -### Detector Base Classes -| Class | Use Case | -|-------|----------| -| `Detector` | Interface -- implement directly for simple detectors | -| `AbstractRegexDetector` | Regex-based pattern matching (most detectors) | -| `AbstractJavaParserDetector` | Java AST via JavaParser (Spring, JPA, etc.) | -| `AbstractAntlrDetector` | ANTLR grammar-based (TS, Python, Go, C#, Rust, C++) | -| `AbstractStructuredDetector` | Structured file parsing (YAML, JSON, TOML, etc.) | -| `AbstractPythonAntlrDetector` | Python ANTLR detectors (shared parse, getBaseClassesText, extractClassBody) | -| `AbstractPythonDbDetector` | Python ORM detectors (adds ensureDbNode/addDbEdge via DetectorDbHelper) | -| `AbstractTypeScriptDetector` | TypeScript regex detectors (shared getSupportedLanguages, detect→detectWithRegex) | -| `AbstractJavaMessagingDetector` | Java messaging detectors (shared CLASS_RE, extractClassName, addMessagingEdge) | - -### Shared Detector Helpers -| Class | Purpose | -|-------|---------| -| `DetectorDbHelper` | Static ensureDbNode/addDbEdge for any detector emitting DATABASE_CONNECTION nodes | -| `FrontendDetectorHelper` | Static createComponentNode/lineAt for Angular, React, Vue detectors | -| `StructuresDetectorHelper` | Static addImportEdge/createStructureNode for Scala/Kotlin structures | +1. Create file in `go/internal/detector//my_detector.go`. +2. Implement the `detector.Detector` interface: -## Testing + ```go + package mycategory -```bash -# Run all tests (~3219 tests) -mvn test + import ( + "github.com/randomcodespace/codeiq/go/internal/detector" + "github.com/randomcodespace/codeiq/go/internal/detector/base" + "github.com/randomcodespace/codeiq/go/internal/model" + ) -# Run a specific test class -mvn test -Dtest=SpringRestDetectorTest + type MyDetector struct{} -# Run E2E quality tests (requires cloned test repo) -E2E_PETCLINIC_DIR=/path/to/spring-petclinic mvn test -Dtest=E2EQualityTest + func NewMyDetector() *MyDetector { return &MyDetector{} } -# Run with verbose output -mvn test -Dsurefire.useFile=false -``` + func (MyDetector) Name() string { return "my_detector" } + func (MyDetector) SupportedLanguages() []string { return []string{"java"} } + func (MyDetector) DefaultConfidence() model.Confidence { return base.RegexDetectorDefaultConfidence } -- Every detector needs: positive match test, negative match test, determinism test -- Server tests use standalone MockMvc (no Spring context needed) -- MCP tools tested by calling `McpTools` methods directly -- E2E quality tests validate against Context7-sourced ground truth (21 tests for petclinic) -- Use `@ActiveProfiles("test")` for any `@SpringBootTest` to avoid Neo4j startup + func init() { detector.RegisterDefault(NewMyDetector()) } -### E2E Quality Testing Strategy (mandatory for detection changes) -1. Build ground truth using Context7 for well-known repos -2. Clone official repo, run full pipeline (index → enrich → serve) -3. Query ALL API endpoints, validate against ground truth -4. Fix findings in loop with parallel agents until 95%+ pass rate -5. Ground truth files: `src/test/resources/e2e/ground-truth-*.json` + func (MyDetector) Detect(ctx *detector.Context) *detector.Result { + // … pattern matching → return detector.ResultOf(nodes, edges) + return detector.EmptyResult() + } + ``` -## Build Commands +3. **CRITICAL** — if the package is a NEW directory under + `internal/detector/`, blank-import it in + `go/internal/cli/detectors_register.go`. Existing directories + already covered. +4. Add a test file at the same path (`my_detector_test.go`). Include + positive match, negative match, determinism (run twice, assert + identical output). +5. `cd go && CGO_ENABLED=1 go test ./internal/detector//... + -count=1`. -```bash -# Build (skip tests) -mvn clean package -DskipTests +### Detector base helpers -# Build + test -mvn clean package +| File | Purpose | +|---|---| +| `base/regex.go` | `FindLineNumber`, `RegexDetectorDefaultConfidence`. | +| `base/imports_helpers.go` | `EnsureFileAnchor`, `EnsureExternalAnchor` — emit anchor nodes so imports/depends_on edges survive `Snapshot`'s phantom filter. | +| `base/component.go` | `CreateComponentNode` for React/Vue/Angular component detectors. | +| `base/structures.go` | `AddImportEdge`, `CreateStructureNode` for Scala/Kotlin/etc structure detectors. | -# Run pipeline -java -jar target/code-iq-*-cli.jar index /path/to/repo -java -jar target/code-iq-*-cli.jar enrich /path/to/repo -java -jar target/code-iq-*-cli.jar serve /path/to/repo +## Configuration -# SpotBugs static analysis -mvn spotbugs:check +`codeiq.yml` at the repo root. Resolution order (last wins): -# OWASP dependency vulnerability check -mvn dependency-check:check -``` +1. Built-in defaults +2. `~/.codeiq/config.yml` +3. `./codeiq.yml` +4. `CODEIQ_
_` env vars +5. CLI flags -## Key Files +`codeiq config validate` + `codeiq config explain`. -| File | Purpose | -|------|---------| -| `CodeIqApplication.java` | Spring Boot main class | -| `analyzer/Analyzer.java` | Pipeline orchestrator (discovery -> detect -> build -> link -> classify) | -| `analyzer/FileDiscovery.java` | File discovery via git ls-files or directory walk | -| `analyzer/GraphBuilder.java` | Buffered graph construction (nodes first, then edges) | -| `analyzer/LayerClassifier.java` | Deterministic layer classification (kind + framework + path heuristics) | -| `analyzer/ServiceDetector.java` | Service boundary detection from build files (30+ build systems) | -| `analyzer/linker/*.java` | Cross-file linkers: TopicLinker, EntityLinker, ModuleContainmentLinker | -| `detector/Detector.java` | Detector interface | -| `model/NodeKind.java` | 34 node types enum | -| `model/EdgeKind.java` | 28 edge types enum | -| `model/CodeNode.java` | Graph node entity | -| `model/CodeEdge.java` | Graph edge entity | -| `graph/GraphStore.java` | Neo4j facade (UNWIND bulk save, Cypher reads, indexes) | -| `config/Neo4jConfig.java` | Embedded Neo4j configuration | -| `config/CodeIqConfig.java` | Application configuration properties | -| `config/JacksonConfig.java` | Jackson config (FAIL_ON_UNKNOWN_PROPERTIES disabled for MCP compat) | -| `cache/AnalysisCache.java` | H2 incremental cache | -| `api/GraphController.java` | REST API endpoints (read-only) | -| `mcp/McpTools.java` | 34 MCP tool definitions (`@McpTool`, read-only) | -| `query/QueryService.java` | Graph query operations with Spring caching | -| `query/StatsService.java` | Rich categorized statistics (7 categories) | -| `query/TopologyService.java` | Service topology queries | -| `cli/IndexCommand.java` | Memory-efficient batched indexing to H2 | -| `cli/EnrichCommand.java` | H2 → Neo4j with linkers, layers, services | -| `cli/ServeCommand.java` | Read-only server startup | -| `intelligence/extractor/LanguageEnricher.java` | Language-specific enrichment orchestrator (Phase 5) | -| `intelligence/extractor/LanguageExtractor.java` | Language extractor interface | -| `intelligence/evidence/EvidencePackAssembler.java` | Evidence pack generation | -| `intelligence/query/QueryPlanner.java` | Intelligent query routing | -| `intelligence/lexical/LexicalEnricher.java` | Doc comment + snippet enrichment | +## Testing -## Code Conventions +```bash +cd go -- Java 25+ features: records, sealed classes, pattern matching, virtual threads -- Spring Boot 4 conventions: constructor injection, `@Component` beans, profile activation -- Spring AI 2.0: `@McpTool`/`@McpToolParam` annotations (not `@Tool`/`@ToolParam`) -- Picocli for CLI with Spring integration (`picocli-spring-boot-starter`) -- Detectors are `@Component` beans -- stateless, thread-safe, auto-discovered -- Framework detectors require discriminator guards (framework-specific imports) -- ID format: `"{prefix}:{filepath}:{type}:{identifier}"` for cross-file uniqueness -- Properties map for detector-specific metadata (`auth_type`, `framework`, `roles`, etc.) -- Spring detectors set `framework: "spring_boot"` on their nodes -- `layer` property on every node: `frontend | backend | infra | shared | unknown` -- Neo4j reads use embedded API (no SDN hydration). Writes use SDN or UNWIND Cypher. -- Neo4j properties round-trip via `prop_*` prefix (written by `bulkSave`, read by `nodeFromNeo4j`) -- Jackson `FAIL_ON_UNKNOWN_PROPERTIES` disabled globally for MCP protocol compatibility -- UTF-8 encoding everywhere (explicit `StandardCharsets.UTF_8`) -- Property key constants: `private static final String PROP_FRAMEWORK = "framework"` — extract when a string literal appears 3+ times in a file +# Full suite +CGO_ENABLED=1 go test ./... -count=1 -## Configuration +# Race detector +CGO_ENABLED=1 go test ./... -race -count=1 -Single source of truth: **`codeiq.yml`** at the repo root. See -`docs/codeiq.yml.example` for the full schema (snake_case throughout; -camelCase accepted as a deprecated alias for one release). Resolution order -(last wins): +# Single package +CGO_ENABLED=1 go test ./internal/detector/jvm/java/... -1. Built-in defaults (`ConfigDefaults.builtIn()`) -2. `~/.codeiq/config.yml` (user-global) -3. `./codeiq.yml` (project) -4. `CODEIQ_
_` env vars (e.g. `CODEIQ_SERVING_PORT=9090`) -5. CLI flags on `codeiq ` +# Verbose +CGO_ENABLED=1 go test ./... -v +``` -Validate and introspect with: +828+ tests. Every detector ships with positive, negative, and +determinism tests. + +## Build Commands ```bash -codeiq config validate -codeiq config explain -``` +cd go -### Spring-owned keys (stay in `application.yml`) +# Build +CGO_ENABLED=1 go build -o /usr/local/bin/codeiq ./cmd/codeiq -A small set of keys still lives in `src/main/resources/application.yml` -because they drive Spring's `@ConditionalOnProperty` / `@Value` wiring and -have not been migrated into `codeiq.yml`: +# Build with version info (release-go.yml does this with goreleaser): +CGO_ENABLED=1 go build \ + -ldflags "-X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Version=v1.0.0' \ + -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Commit=$(git rev-parse --short HEAD)' \ + -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)'" \ + -o /usr/local/bin/codeiq ./cmd/codeiq +``` + +Release pipeline: +[`shared/runbooks/release-go.md`](shared/runbooks/release-go.md). -- `codeiq.neo4j.enabled` -- profile-conditional toggle (`false` in the - `indexing` profile, `true` in `serving`). -- `codeiq.neo4j.bolt.port` -- embedded Neo4j Bolt listener port. -- `codeiq.cors.allowed-origin-patterns` -- CORS allow-list for the REST API. -- `codeiq.ui.enabled` -- toggles the React SPA static resource handler. +## Code Conventions -`UnifiedConfigBeans` bridges the unified config to the legacy `CodeIqConfig` -bean for code paths that haven't been ported yet. +- Go 1.25+ idioms — generics where they reduce repetition, `slices.` + and `maps.` over hand-rolled loops, `min`/`max` builtins. +- `model.Confidence` and `Source` are mandatory on every `CodeNode` / + `CodeEdge`. Base classes stamp the per-detector floor at the + orchestration boundary (LEXICAL for regex bases, SYNTACTIC for + AST/structured bases). +- Property union semantics: in `mergeNode`, donor only fills keys the + survivor doesn't already have. Don't clobber a high-confidence + detector's framework/auth_type stamping. +- ID format: `:::` — keep prefixes + stable; the GraphBuilder dedup map relies on them. +- File-anchor / external-anchor IDs: + - `:file:` for the file-as-module + - `:external:` for imported packages + This pattern saves imports edges from phantom drop. +- Detectors with framework guards: require a framework-specific + import before emitting (e.g. Quarkus requires `io.quarkus`). +- UTF-8 everywhere — explicit `[]byte` only when interfacing with + Kuzu or SQLite. ## Gotchas & Lessons Learned -- **Pipeline is index → enrich → serve**: Don't put analysis/enrichment in serve. Serve is read-only. -- **MCP/API is read-only**: No data manipulation from serving layer. Remote servers may lack source code. -- **Framework false positives**: Quarkus/Micronaut/Fastify detectors matched generic patterns (router.get, @Transactional). Always add discriminator guards requiring framework-specific imports. -- **Neo4j property round-trip**: Properties stored as `prop_*` keys in Neo4j. `nodeFromNeo4j()` must restore them. Verify properties survive write→read. -- **Edge persistence**: Edges must be attached to source nodes before `bulkSave()`. MATCH silently returns 0 rows for missing nodes -- pre-validate IDs. -- **ServiceDetector must scan filesystem**: Don't rely on node file paths for build file detection. Many build files (pom.xml) don't produce CodeNodes. Walk the filesystem directly. -- **Generic, not example-specific**: Every feature must work for ALL architectures. Don't fix for the specific example given and forget other ecosystems. -- **Neo4j indexes**: Created by `enrich` on `id`, `kind`, `layer`, `module`, `filePath`, `label_lower`, `fqn_lower`, plus two fulltext indexes (`search_index` over `[label_lower, fqn_lower]` and `lexical_index` over `[prop_lex_comment, prop_lex_config_keys]`). Critical for query performance and free-text search on large graphs. -- **Default batch size is 500**: Performs better than 1000 for indexing. -- **Spring Boot startup overhead**: 8-16s for embedded Neo4j + Spring context init. -- **Virtual thread concurrency on the H2 cache**: JDK 25 + JEP 491 means neither `synchronized` nor `java.util.concurrent.locks.*` pin virtual-thread carriers, so the lock primitive is no longer the constraint. `AnalysisCache` uses a `ReentrantReadWriteLock` so virtual threads can read in parallel while writes stay serialized — this is what prevents `ClosedChannelException` from concurrent writes against H2's MVStore file channel. Do not regress to coarse `synchronized` methods "for virtual-thread safety"; that advice is stale. -- **ANTLR generated sources**: Generated during `mvn generate-sources` from `.g4` files. Do not edit. -- **`@ActiveProfiles("test")`**: Required on any `@SpringBootTest` to avoid Neo4j startup conflicts. -- **Dead code detection**: Must filter by semantic edges only (calls, imports, depends_on). Exclude structural edges (contains, defines) and entry points (endpoints, config files). -- **H2 reserved words**: `key`, `value`, `order` are reserved in H2 SQL. Use `meta_key`, `meta_value` etc. in CREATE TABLE statements. -- **Cache versioning**: `AnalysisCache` has a `CACHE_VERSION` constant (currently `5`, bumped from `4` for the resolver `confidence` + `source` schema). Bump it when changing the hash algorithm, H2 schema, or any field that becomes mandatory on cached nodes/edges so stale caches are auto-cleared on next run. -- **Symbol resolver runs at index-time only.** `Analyzer.bootstrapResolvers()` and `Analyzer.resolveFor()` are wired into `run` / `runBatchedIndex` / `runSmartIndex` paths only — never at `serve`. The resolver SPI lives under `intelligence/resolver/`. If you find yourself reaching for `ResolverRegistry` from a serve-mode code path, stop — the graph is the source of truth at serve. -- **`Confidence` + `source` are mandatory on every `CodeNode` / `CodeEdge`.** `DetectorEmissionDefaults.applyDefaults` stamps the per-detector floor (`LEXICAL` for regex bases, `SYNTACTIC` for AST/JavaParser/structured bases) at the orchestration boundary; detectors that consume `ctx.resolved()` upgrade to `Confidence.RESOLVED` and attach a `target_fqn` property. Reading legacy data without these fields is non-throwing — they read back as `LEXICAL` / null. -- **`JavaSymbolResolver.resolve()` allocates a fresh `JavaParser` per call.** JavaParser instances aren't thread-safe and `resolve()` is invoked from virtual threads concurrently. Per-call allocation is intentional, not a perf bug — don't "optimize" by sharing one parser across calls. -- **`JavaSymbolResolver.resolve(String)` enforces strict parse-success.** When JavaParser flags any problem (`!parseResult.isSuccessful()`), the resolver returns `EmptyResolved.INSTANCE` rather than a partial-CU `JavaResolved`. This prevents silent simple-name-only edges from broken parses that look like RESOLVED-tier coverage. Detectors must treat `ctx.resolved()` returning `EmptyResolved` as "lexical fallback" — never assume RESOLVED edges land for every Java file. -- **`JavaSymbolResolver` fields are `volatile`.** `combined` and `solver` are written by `bootstrap()` and read by `resolve()` + the public accessors from arbitrary virtual-thread carriers. The JLS Thread Start Rule covers the `executor.submit()` path; `volatile` covers post-bootstrap callers on other threads. Don't drop the keyword. -- **FileHasher uses SHA-256**: Changed from MD5. Hash output is 64 hex chars (not 32). Tests must expect 64-char hashes. -- **SnakeYAML parses `on` as Boolean.TRUE**: In YAML files, bare `on` key becomes `Boolean.TRUE`. Use `String.valueOf(key)` comparisons, not `Boolean.TRUE.equals(key)` (SonarCloud S2159). -- **Regex possessive quantifiers**: Use `*+` instead of `*` for nested quantifiers like `([^"\\]*(?:\\.[^"\\]*)*)` → `([^"\\]*+(?:\\.[^"\\]*+)*+)` to prevent stack overflow (SonarCloud S5998). -- **Parallel agent conflicts**: Don't dispatch multiple agents editing the same files concurrently. Use worktree isolation or sequential execution. -- **SonarCloud project key**: `RandomCodeSpace_codeiq`, org: `randomcodespace` -- **CI workflow**: Single `ci-java.yml` runs build + SonarCloud analysis. No cross-platform builds needed (JVM). -- **Spring Security only loads in the `serving` profile.** `application.yml` excludes `SecurityAutoConfiguration` + `SecurityFilterAutoConfiguration` + `UserDetailsServiceAutoConfiguration` at the **default** level so adding `spring-boot-starter-security` doesn't break ~3000 MockMvc tests by activating a default HTTP Basic chain. The `serving` profile re-enables them by listing only `UserDetailsServiceAutoConfiguration` (suppresses the auto user/password printout); the chain itself is built by `config/security/SecurityConfig`. **Don't** drop the default exclude — non-serving contexts (CLI, tests) must have no Spring Security wiring at all. -- **`BearerAuthFilter.shouldNotFilter` and `SecurityConfig.permitAll()` paths must stay in sync.** The filter runs before Spring's `AuthorizationFilter`, so if a path is in `permitAll()` but NOT in `shouldNotFilter`, the filter rejects it with 401 before Spring's chain can permit it. Open paths today: `/`, `/index.html`, `/favicon.ico`, `/assets/**`, `/static/**`, `/error`, `/actuator/health`, `/actuator/health/liveness`, `/actuator/health/readiness`. Adding any new permit-all endpoint requires updating BOTH places. -- **Constant-time bearer-token compare uses SHA-256 pre-hash.** Both the provided and expected token are hashed with SHA-256 before `MessageDigest.isEqual`. SHA-256 always produces 32-byte digests, so `isEqual` runs over fixed-size arrays — defeats the length oracle that makes raw `isEqual` unsafe across mismatched-length inputs. **Don't** "optimize" by removing the hash and comparing raw token bytes; that re-introduces the oracle. -- **Never log the `Authorization` header.** `BearerAuthFilter` deliberately never passes the header value to a logger, even at DEBUG. The rejection log line carries only `method` and `requestURI`. There's a regression test (`tokenValueNeverAppearsInLogs`) that captures all log lines for the filter and asserts the secret substring is absent. -- **`mode=none` + active `serving` profile = startup failure** unless `codeiq.mcp.auth.allow_unauthenticated=true` is **explicitly** set. This is by design — operators must opt into permissive mode deliberately. `mode=mtls` is reserved and currently throws "not yet implemented" (better than silently passing through). -- **`server.error.include-stacktrace: never`** is set in the serving profile as defense-in-depth alongside `GlobalExceptionHandler`. Don't enable it for "easier debugging" — stack frames in the response body leak class names + paths (CWE-209). Use the `request_id` in the envelope to correlate to the WARN log line where the full stack is captured. -- **Cypher transaction wall-clock cap is configured at the DBMS level**, not per-call. `Neo4jConfig.databaseManagementService(...)` sets `GraphDatabaseSettings.transaction_timeout = 30s` so every transaction gets the cap automatically. Don't reach for `graphDb.beginTx(timeout, unit)` overload in tool code — the test suite mocks `beginTx()` with no args and the overload changes the matcher signature, breaking the existing stubs across `McpToolsTest` / `McpToolsExpandedTest` / `McpToolsEvidenceTest`. -- **`McpTools.runCypher` row cap is enforced in the iteration loop, not via `LIMIT`.** After `maxResults` rows are accumulated the loop breaks and the response carries `truncated: true` + `max_results: N`. Don't try to inject `LIMIT N` into the user-supplied query string — that would require parsing the query (and the user's query may already have its own LIMIT). -- **`McpTools.getCachedData()` 60-second TTL snapshot is a bridge fix.** It's NOT the proper solution — the proper solution is to rewrite each topology MCP tool to use a targeted Cypher query so the full graph never needs to live on heap. The cache caps peak memory under concurrent calls but the snapshot itself is still multi-GB on large graphs. When that refactor lands, the `AtomicReference` and `getCachedData()` itself can be deleted. -- **`RateLimitFilter` keys by `sha256(Authorization)`** — the raw token NEVER goes into the bucket key map. The 16-hex-char digest is enough collision resistance for keying. Falls back to `X-Forwarded-For` (first hop) → `RemoteAddr` when no auth header is present. Buckets live in a `ConcurrentHashMap` — bounded in practice by `num_distinct_clients`, which for the single-tenant pod shape is small. Swap to a Caffeine cache with a max-size eviction if multi-tenant exposure is ever added. -- **Filter chain order in `serving` profile**: `SecurityHeadersFilter` → `RateLimitFilter` → `BearerAuthFilter` → ... → controller. Each `addFilterBefore(X, UsernamePasswordAuthenticationFilter.class)` inserts X immediately before UPAFilter, pushing the previously-inserted filter farther from the target — so the **registration order in `SecurityConfig.servingFilterChain` IS the chain order**. Don't shuffle without re-reasoning about it: if `RateLimitFilter` ran AFTER `BearerAuthFilter`, an unauthenticated brute-force attempt would never get throttled (would just see 401 over and over, hitting the slow path). -- **`Files.probeContentType` is best-effort** — JDK 25 on Linux uses `/etc/mime.types` + magic-byte fallback. It returns `null` if the type can't be determined; treat that as "let it through" (the byte cap in `SafeFileReader` still bounds size). The allowlist for `/api/file` is `text/*` + `application/{json,xml,x-yaml,javascript}` — extending requires adding to the explicit list in `GraphController.readFile`. -- **Sanitize user-controlled values before logging.** `BearerAuthFilter.sanitizeForLog(String)` strips `\p{Cntrl}` and truncates at 256 chars. Use it on anything tainted by `request.getRequestURI()`, `request.getMethod()`, headers, etc. before passing to a logger. CodeQL `java/log-injection` will flag direct `log.warn("... {} ...", request.getRequestURI())` as a vuln. -- **`mcp.limits.max_depth` is a NEW field on `McpLimitsConfig`** (default 10). Audit #10 / C3 — the original audit assumed it existed but it didn't. When adding new MCP traversal tools, cap depth via `Math.min(callerSupplied, maxDepth)` before passing to Cypher. The REST endpoint already had this guard via `config.getMaxDepth()` from `CodeIqConfig`; the MCP path now mirrors it via `McpLimitsConfig.maxDepth()`. -- **`codeiq bundle` writes `checksums.sha256` LAST and excludes itself.** `BundleCommand#writeChecksumsManifest` runs after every other entry has been written, then the digests collected in `LinkedHashMap checksums` are emitted as ` \n` per line — exactly GNU coreutils `sha256sum` format, so receivers verify with `sha256sum -c checksums.sha256`. The manifest itself is intentionally NOT in the digest list (would be circular); to verify `checksums.sha256` against tampering, sign the bundle.zip out-of-band (Sigstore, GPG, or compare to the GitHub Release SHA-256). Don't try to "fix" the circular omission by hashing checksums.sha256 into the manifest — that turns into a cat-and-mouse loop. -- **`writeFileHashed` reads each file once, feeding both the SHA-256 and the ZIP stream.** Hundreds-of-MB graph DBs / CLI JARs can't be double-read for a separate hash pass. The 8KB chunk size in `BundleCommand` is small enough to keep memory flat regardless of file size; do NOT collect bytes into a `byte[]` and then split for "convenience". -- **`serve.sh` and `serve.bat` MUST NOT contain network calls.** Audit RAN-46 §3 — air-gapped deploy model. Pre-PR-3 these scripts had `curl -fL https://repo1.maven.org/...` to download the CLI JAR on first run; that's gone. Receivers must `--include-jar` when bundling or stage the JAR from an internal mirror. There's a regression test in `BundleCommandTest#bundleCreatesZipWithCorrectStructure` that asserts `serve.sh` contains neither `curl` nor `maven.org` — keep that test green. -- **`.dockerignore` does NOT inherit `.gitignore`.** Docker resolves COPY against the build context, which includes uncommitted/untracked working-tree files. `.gitignore` only stops things being staged; it has no effect on what `docker build` sees. Mirror the secret-pattern globs explicitly in `.dockerignore` (`.env*`, `*.jks`, `id_rsa`, `credentials.{json,yaml}`, etc.). Pre-PR-3 the `.dockerignore` was 9 lines and would have shipped a `.env.prod` straight into a published image. -- **Semgrep is pinned to `semgrep==1.161.0`** in `.github/workflows/security.yml`. Bumps go through Dependabot's pip ecosystem on a documented cadence — `pip install --upgrade semgrep` (floating) was previously flagged by Scorecard `Pinned-Dependencies`. Don't unpin to "always get latest"; a CI-time auto-bump on a security-scanner can break the build silently when the new release adds rules. -- **`RequestIdFilter` MUST stay outermost in the security chain.** Filter chain order (set in `SecurityConfig#servingFilterChain`): RequestIdFilter → SecurityHeadersFilter → RateLimitFilter → BearerAuthFilter. If you reorder and put RequestIdFilter inside, the rate-limit reject and auth-reject log lines will fire BEFORE MDC is populated, and clients won't get a correlated `X-Request-Id` response header on 401/429. The filter is registered LAST in the `addFilterBefore(..., UPAFilter.class)` sequence because each `addFilterBefore` pushes the previously-inserted filter further from the target — so the LAST registration is the OUTERMOST in the actual chain. -- **Inbound `X-Request-Id` is allow-list validated, NOT escaped.** `RequestIdFilter` accepts only `[A-Za-z0-9_-]{8,64}`; anything else is replaced with a generated UUID. Don't try to "be helpful" by lowercasing/trimming — the allow-list is the defense, not the sanitizer. CWE-117 log-forging via `X-Request-Id: \nINFO: granted access` is impossible because the value never reaches a logger before validation. -- **MDC must be cleared in finally — even on throw.** `RequestIdFilter.doFilterInternal` puts MDC.request_id, runs the chain in a try-block, and clears in finally. There's a regression test (`RequestIdFilterTest#clearsMdcEvenWhenChainThrows`) that asserts the clear runs when the chain throws. Tomcat's NIO worker pool and virtual-thread carriers both reuse threads; a leaked MDC entry from request N is visible to request N+1 if you skip the finally. -- **`GraphHealthIndicator` is on the readiness probe ONLY.** Configured via `management.endpoint.health.group.{liveness,readiness}` in `application.yml`. Liveness = "JVM up; restart on fail". Readiness = "graph loaded; route traffic only when up". Putting `graphHealthIndicator` on the liveness probe means a graph-down event flaps the pod (k8s killing it) instead of just routing away. If you add another HealthIndicator that's about app health (not infra dependencies), it goes on liveness; if it's about a specific dependency (DB, message bus), it goes on readiness. -- **Logback `serving` profile uses JSON, others use plaintext.** `logback-spring.xml` defines a `JSON` appender (LogstashEncoder) used only by the `` block. CLI / indexing / default profiles use the `CONSOLE` (plaintext `%msg%n`) appender so that `codeiq index` doesn't dump JSON-shaped log lines into the user's terminal. Don't switch the global default appender to JSON — the CLI is interactive and the project deliberately uses `System.out` for status messages alongside the logger. -- **MCP errors return a structured envelope `{code, message, request_id, error}`.** `McpTools#errorEnvelope(code, exception)` is the canonical wrapper. Codes: `INTERNAL_ERROR` (catch-all), `INVALID_INPUT` (IllegalArgumentException), `FILE_READ_FAILED` (file IO), `SERIALIZATION_FAILED` (Jackson). The legacy `error` field is preserved for backwards-compat with older MCP clients reading `error` directly — DON'T remove it without grepping for clients in this org first. Full exception always logged server-side at WARN with request_id; only sanitized envelope reaches the client. -- **`/actuator/prometheus` is bearer-authenticated, NOT permitAll.** It matches the `/actuator/**` rule in `SecurityConfig`. Don't add `prometheus` to the permitAll list "for the scraper" — Prometheus's `bearer_token_file` config field exists for exactly this case. Anonymous metric scraping is reconnaissance data (request rates, error counts, JVM internals). The application tag `codeiq` is set via `management.metrics.tags.application` so multi-pod ingestion is filterable. - -## Supply-chain observability (OpenSSF) - -Two OpenSSF signals are published. **`shared/runbooks/engineering-standards.md` §1 + §5 is the SSoT for the security stack** — this section is the operator-level summary. - -### Best Practices badge - -- Project: https://www.bestpractices.dev/projects/12650 — registered 2026-04-25 by the board. -- Manifest: `.bestpractices.json` at repo root (project_id, evidence map, audit dates). -- **Hard gate per the board: badge level `passing`.** The final `in_progress` → `passing` flip happens in the bestpractices.dev admin UI (board-owned). Repo-side criteria (CHANGELOG, SECURITY.md, signed commits, OSS-CLI security stack, Scorecard wiring, dependency updates) are evidenced via the manifest above. - -### Scorecard baseline + target - -- Workflow: [`.github/workflows/scorecard.yml`](.github/workflows/scorecard.yml) — push to `main`, weekly cron (Mondays 06:00 UTC), `workflow_dispatch`. SARIF lands on the Security tab; results also publish to https://api.securityscorecards.dev/projects/github.com/RandomCodeSpace/codeiq. -- **Baseline (RAN-52 close, 2026-04-26):** read live from the Scorecard project page above; no static checked-in score (it would rot). -- **Target:** ≥ **8.0 / 10** stretch, with these checks at max: `Pinned-Dependencies`, `Token-Permissions`, `Branch-Protection`, `Code-Review`, `Maintained`, `License`, `SAST`, `Vulnerabilities`. Scorecard is observational; the `passing` Best Practices badge is the only hard gate per the board. -- **Known floor reductions:** `Webhooks` (no public webhook surface — N/A); `Signed-Releases` (release-java workflow signs the GA commit; we are not yet signing every release artifact via Sigstore — tracked under follow-up). - -### OSS-CLI security stack (path B board ruling — RAN-46 AC §3) - -[`.github/workflows/security.yml`](.github/workflows/security.yml) runs six gate-blocking jobs: **OSV-Scanner** (SCA on the npm lockfile), **Trivy** (filesystem + Maven + OS scan), **Semgrep** (SAST: `p/security-audit` + `p/owasp-top-ten` + `p/java`), **Gitleaks** (secret scan, full git history), **jscpd** (duplication < 3% on production code), and **`anchore/sbom-action`** (SPDX + CycloneDX SBOM, artifact-only). Push + PR + weekly cron. Per the path-B board ruling, **do not re-introduce SonarCloud, CodeQL, or any NVD-direct tool (e.g. OWASP Dependency-Check)** without an explicit board reversal — see engineering-standards.md §5.1. - -## Deploy - -codeiq's deploy surface is **Maven Central + GitHub Releases** (per RAN-46 AC #10 ruling, option a). The single Java JAR (with the React UI bundled inside) is published via two `workflow_dispatch`-only workflows: `.github/workflows/beta-java.yml` (manual beta cut → Sonatype Central beta + GitHub pre-release) and `.github/workflows/release-java.yml` (manual GA cut with a `version` input → the workflow builds a GPG-signed release commit on a detached HEAD, deploys from that exact tree, then creates and pushes a GPG-signed annotated `vX.Y.Z` tag pointing at the release commit + a GitHub Release). There is no static-CDN frontend, no hosted backend, no VPS — codeiq runs on the developer's machine. See [`shared/runbooks/release.md`](shared/runbooks/release.md) and [`shared/runbooks/engineering-standards.md`](shared/runbooks/engineering-standards.md) §7.1. +### Pipeline + +- **Pipeline is `index → enrich → (mcp|stats|query)`.** Don't put + analysis in MCP. MCP is read-only. +- **Detector registration choke point** (`internal/cli/detectors_register.go`). + Forgetting the blank import ships an empty registry for that + language. Caught by the polyglot benchmark — 15 language families + silently produced 0 nodes pre-fix. Test: `codeiq plugins` lists + every detector by name; new ones must appear. + +### Kuzu v0.7.1 quirks + +- FTS extension not bundled, not downloadable offline. `INSTALL fts` + errors with "fts is not an official extension". `CreateIndexes()` + no-ops FTS; `SearchByLabel` / `SearchLexical` use case-insensitive + `CONTAINS` predicates. +- LIMIT / SKIP can't be parameterized. Inline as literals; + parameterize the needle only. +- Uses `lower()` (SQL) not `toLower()` (openCypher). +- `RETURN DISTINCT` scope tighter than openCypher; `ORDER BY` must + reference the projected alias, not the bound variable. +- List comprehension binder rejects out-of-scope variables. Use + `properties(nodes(p), 'id')` instead of `[n IN nodes(p) | n.id]`. +- `EXISTS { … }` subquery doesn't see outer-scope `$param`. Inline + static lists as rel-pattern alternations. +- Go binding's `goValueToKuzuValue` accepts `[]any` only. Added + `stringsToAny` widener for `IN $param` use cases. +- Multi-label rel alternation + kleene-star in the same recursive + pattern breaks the binder. BlastRadius uses an anonymous recursive + pattern. + +### MCP SDK v1.6 + +- No `NewStdioTransport(in, out)` helper. `StdioTransport{}` + zero-value bound to `os.Stdin`/`os.Stdout`. Tests use + `NewInMemoryTransports()`. +- `Server.AddTool(t *Tool, h ToolHandler)` — two args, not aggregate. +- `CallToolRequest.Params` is `*CallToolParamsRaw{Arguments + json.RawMessage}`. Wrapper unmarshals once, hands raw JSON to the + handler. +- ToolHandler JSON-marshals returned values. Special-case `string` + in `mcp/tool.go` for the `generate_flow` rendered output — + otherwise the Mermaid/DOT string gets double-encoded. + +### Go RE2 vs Java regex + +- No lookahead / lookbehind. Plan-spec patterns like + `CALL\s+(?!db\.)` won't compile. Rewrites: two-stage match (collect + every CALL site, then allow-list each procedure name). +- No possessive quantifiers (`*+`). RE2 doesn't need them — its NFA + doesn't backtrack. Strip them when porting Java regex. +- No DOTALL — use `(?s)` prefix. + +### Detector authoring traps + +- **Phantom edges**: emit edges with anchor nodes on both ends + (`base.EnsureFileAnchor` + `base.EnsureExternalAnchor`). Without + anchors, the edge drops at Snapshot. +- **Discriminator guards**: framework detectors must require a + framework-specific import or annotation before emitting. Without a + guard, generic patterns (e.g. `@Transactional`) match across + unrelated frameworks and produce false positives. +- **Determinism**: never iterate a Go `map` without sorting keys + first. Run the determinism test twice with `count=1` to catch this. + +### Filesystem & paths + +- File discovery dir-walk fallback ingests `node_modules/`, + `vendor/`, `target/`, etc. — see `DefaultExcludeDirs` in + `analyzer/file_discovery.go`. Add new ignored dirs there. +- `Files.probeContentType` is best-effort on Linux (JDK note from the + Java side — replaced in Go by `net/http.DetectContentType` plus an + explicit allowlist in `mcp/read_file.go`). + +### Performance + +- CertificateAuthDetector once consumed 99% of indexing CPU on + C#-heavy projects because its pre-screen included `.cert` / `.crt` + / `.pem` substrings that match `using + System.Security.Cryptography.X509Certificates;`. Use a STRICT + keyword list (high-signal markers only — not path extensions) in + any cross-language regex pre-screen. + +### Release / signing + +- Release tag must be `v*.*.*`; pre-releases use the + `vX.Y.Z-rc.N` form (Goreleaser `prerelease: auto` honors it). +- Cosign keyless via GitHub OIDC — no long-lived key on the runner. + Verification needs the cert + sig + the OIDC identity regex (see + `shared/runbooks/release-go.md`). +- Homebrew tap publish is opt-in via `HOMEBREW_TAP_GITHUB_TOKEN`. + Forks leave the secret unset and the brew step skips silently. ## Updating This File -After significant changes (new detectors, new endpoints, architectural decisions, conventions learned), update this CLAUDE.md to reflect the current state. Keep it concise and actionable. +After significant changes (new detectors, new MCP tools, architectural +decisions, conventions learned), update this file. Keep it concise. +The full pre-cutover Java-side history of these notes is on the +squash-merge `c363727`; reach for that via `git show` when you need +context. diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md index f718c8a2..065b5003 100644 --- a/PROJECT_SUMMARY.md +++ b/PROJECT_SUMMARY.md @@ -1,162 +1,154 @@ # Project Summary: codeiq -> Generated by `project-summarizer` on 2026-04-27. Audience: AI agents (and humans) who need to understand and modify this codebase. Every claim should be checkable; items marked `[inferred]` were not directly verified. +> Refreshed 2026-05-13 after Phase 6 cutover (v1.0.0). Audience: AI +> agents (and humans) who need to understand and modify this codebase. > -> **Canonical depth lives in [`CLAUDE.md`](CLAUDE.md)** (~28 KB, agent-oriented, hand-maintained). This file is a thin entry point that summarizes and links into [`CLAUDE.md`](CLAUDE.md), the runbooks under [`shared/runbooks/`](shared/runbooks/), and the deep-dives under [`docs/project/`](docs/project/). Treat `CLAUDE.md` as the source of truth where they overlap. +> **Canonical depth lives in [`CLAUDE.md`](CLAUDE.md)** (~16 KB, +> agent-oriented, hand-maintained). This file is a thin entry point +> that links into `CLAUDE.md`, the runbooks under +> [`shared/runbooks/`](shared/runbooks/), and the deep-dives under +> [`docs/project/`](docs/project/). ## Identity -- **What it is:** CLI tool + read-only server that scans codebases and builds a deterministic code knowledge graph (no AI, no external APIs — pure static analysis) with a Spring AI MCP server, REST API, and React UI on top of an embedded Neo4j graph. See [`README.md`](README.md), [`CLAUDE.md`](CLAUDE.md) §"What This Project Is". -- **Type:** monorepo (Java backend + React SPA bundled into one JAR) — combined CLI + library + read-only web service. -- **Status:** **active** — 30+ commits in the last 7 days on `main` (mostly RAN-46/52/57 supply-chain work). Last non-checkpoint commit `92c6e00` on 2026-04-26. Several `checkpoint: pre-yolo` auto-commits are noise from a session hook, not real activity. -- **Maven coordinates:** `io.github.randomcodespace.iq:code-iq` (see `` / `` in `pom.xml`). CLI command: `codeiq` (via `java -jar code-iq-*-cli.jar`). -- **Primary languages:** Java 25 (server, CLI, all detectors); TypeScript 5.7 + React 18 (SPA at `src/main/frontend/`). +- **What it is**: a CLI + MCP server that scans a codebase and emits a + deterministic code knowledge graph — services, endpoints, entities, + infrastructure, auth patterns, framework usage. No AI, pure static + analysis. LLM is opt-in via `codeiq review`. +- **Type**: CLI tool + MCP stdio server, single static binary. +- **Status**: v1.0.0 (Phase 6 cutover landed 2026-05-13). Active. +- **Primary language**: Go 1.25.10. CGO required. ## Tech stack -Read directly from the `pom.xml` `` block and `src/main/frontend/package.json`. - -| Layer | Tech | Source | -|-------|------|--------| -| Runtime | Java 25 | `pom.xml` `25` | -| Web/DI | Spring Boot 4.0.5 | `pom.xml` (parent `spring-boot-starter-parent`) | -| Graph DB | Neo4j Embedded 2026.02.3 (Community) | `pom.xml` `` | -| MCP | Spring AI 2.0.0-M3 (`spring-ai-starter-mcp-server-webmvc`) | `pom.xml` `` | -| CLI | Picocli 4.7.7 (`picocli-spring-boot-starter`) | `pom.xml` `` | -| AST + symbols (Java) | JavaParser 3.28.0 + `javaparser-symbol-solver-core` 3.28.0 (Apache-2.0) | `pom.xml` `javaparser` deps; `intelligence/resolver/java/JavaSymbolResolver.java` | -| Parsers (35+ langs) | ANTLR 4.13.2 (TS/JS, Python, Go, C#, Rust, C++) | `[CLAUDE.md]` | -| Cache | H2 in embedded mode (incremental analysis cache) | `src/main/java/io/github/randomcodespace/iq/cache/AnalysisCache.java` | -| Frontend | React 18.3 + AntD 5.24 + ECharts 5.6 + react-router 7 | `src/main/frontend/package.json` | -| Frontend build | Vite 6.4 + TS 5.7 → bundled into `src/main/resources/static/` | `src/main/frontend/vite.config.ts` | -| Tests | JUnit (236 test files), Playwright for SPA E2E | `find src/test/java -name '*.java' \| wc -l` = 236 | -| Static analysis | SpotBugs 4.9.8.3, Jacoco 0.8.14, Checkstyle 3.6.0 | `pom.xml` `` / `` / `` | -| Security gates | OSV-Scanner, Trivy, Semgrep, Gitleaks, jscpd, SBOM | `.github/workflows/security.yml` | -| Supply chain | OpenSSF Scorecard + Best Practices (project_id 12650) | `.github/workflows/scorecard.yml`, `.bestpractices.json` | - -**Pinned security overrides** (bumps inside Spring Boot 4.0.5's BOM): Tomcat 11.0.21 (CVE-2026-34483/34487/34500), Jackson 3.1.1 (GHSA-2m67-wjpj-xhg9). Revert when Spring Boot 4.0.6+ catches up. See the `` and `` properties + comments in `pom.xml`. +- **Go 1.25.10** — toolchain pin in `go/go.mod` (module min 1.25.0, + clamped by `modelcontextprotocol/go-sdk`). +- **Kuzu 0.7.1** (`github.com/kuzudb/go-kuzu`) — embedded graph DB. +- **`mattn/go-sqlite3` 1.14.22** — SQLite analysis cache. +- **`smacker/go-tree-sitter`** — AST parsing (Java / Python / TS / Go). +- **`modelcontextprotocol/go-sdk` v1.6** — stdio MCP server. +- **`spf13/cobra`** — CLI framework. +- Manifest files read: `go/go.mod`, `go/go.sum`. ## Entry points | Entrypoint | File | Purpose | |---|---|---| -| CLI / Spring Boot main | `src/main/java/io/github/randomcodespace/iq/CodeIqApplication.java` | Boots Spring, picks `serving` vs `indexing` profile from the first arg, hands control to Picocli | -| CLI dispatcher | `src/main/java/io/github/randomcodespace/iq/cli/CodeIqCli.java` | Top-level Picocli `@Command` with 14 subcommands | -| 14 subcommands | `src/main/java/io/github/randomcodespace/iq/cli/{Index,Enrich,Serve,Analyze,Stats,Graph,Query,Find,Cypher,Topology,Flow,Bundle,Cache,Plugins,Version,Config}Command.java` | One file per CLI command (20 files including subcommands and helpers) | -| REST API (5 controllers) | `src/main/java/io/github/randomcodespace/iq/api/{Graph,Flow,Topology,Intelligence}Controller.java` + `SafeFileReader.java` (helper) | 37 read-only endpoints on `/api/**`, `@Profile("serving")` | -| MCP tools (34 tools) | `src/main/java/io/github/randomcodespace/iq/mcp/McpTools.java` | `@McpTool` methods, auto-registered by Spring AI starter | -| SPA entry | `src/main/frontend/src/main.tsx` → `App.tsx` | React 18 + react-router 7, 4 pages | +| CLI / MCP server | `go/cmd/codeiq/main.go` | The only binary. All subcommands live in `internal/cli`. | +| Subcommand registry | `internal/cli/root.go` | Sets up cobra root + registers per-subcommand inits. | +| Detector registry | `internal/cli/detectors_register.go` | Blank-imports every detector package leaf. **Choke point** — forget it and detectors silently no-op. | +| Stdio MCP | `internal/cli/mcp.go` + `internal/mcp/server.go` | Wires consolidated tools + the deprecated 34 + `review_changes`. | +| Analyzer pipeline | `internal/analyzer/analyzer.go` | FileDiscovery → parser → detectors (pool) → GraphBuilder → SQLite. | +| Enrich pipeline | `internal/analyzer/enrich.go` | SQLite → Kuzu + linkers + layer classifier + intelligence. | ## Directory map ``` codeiq/ -├── pom.xml — Maven build (single module, JAR) -├── CLAUDE.md — canonical agent-oriented internals doc -├── README.md — human-facing intro + quick start -├── AGENTS.md — repo-root agent entry pointer -├── CHANGELOG.md — Keep-a-Changelog -├── SECURITY.md — vuln disclosure policy -├── LICENSE — Apache-2.0 -├── .bestpractices.json — OpenSSF Best Practices manifest -├── spotbugs-exclude.xml — SpotBugs suppressions -├── codeiq.yml — (optional, per-project config) -├── .github/ -│ ├── workflows/ — 5 workflows: beta-java, ci-java, -│ │ release-java, scorecard, security -│ └── dependabot.yml — Maven + GHA + npm, weekly grouped -├── src/ -│ ├── main/ -│ │ ├── java/io/github/randomcodespace/iq/ — Java sources (see CLAUDE.md "Package Structure") -│ │ ├── frontend/ — React SPA (Vite, builds into resources/static/) -│ │ └── resources/ -│ │ ├── application.yml — Spring config (profile-conditional) -│ │ └── static/ — Vite-built SPA assets (gitignored) -│ └── test/java/ — 236 test files (unit + E2E quality) -├── docs/ -│ ├── codeiq.yml.example — full unified-config schema -│ └── superpowers/baselines/ — phase exit-gate snapshots -├── shared/runbooks/ — engineering-standards, release, rollback, -│ first-time-setup, test-strategy -├── scripts/ — repo-local helpers (e.g. signing setup) -└── .codeiq/ — created at runtime: cache/ (H2) + graph/ (Neo4j) +├── go/ — Go module (will move to repo root post-v1) +│ ├── cmd/codeiq/ — main package +│ ├── internal/ +│ │ ├── analyzer/ — pipeline orchestration + linkers +│ │ ├── buildinfo/ — version metadata +│ │ ├── cache/ — SQLite analysis cache +│ │ ├── cli/ — cobra subcommands +│ │ ├── detector/ — 100 detectors organized by category +│ │ ├── flow/ — architecture-flow diagram engine +│ │ ├── graph/ — Kuzu facade (read-only on serve path) +│ │ ├── intelligence/ — lexical + language extractors + evidence + planner +│ │ ├── mcp/ — MCP server + tool definitions +│ │ ├── model/ — CodeNode, CodeEdge, kinds, Confidence +│ │ ├── parser/ — tree-sitter + structured parsers +│ │ ├── query/ — service / topology / stats +│ │ └── review/ — PR-review pipeline (diff + Ollama) +│ ├── parity/ — parity harness (build tag `parity`) +│ ├── testdata/ — fixtures (fixture-minimal, fixture-multi-lang) +│ ├── go.mod +│ └── go.sum +├── .github/workflows/ — go-ci, perf-gate, release-go, security, scorecard +├── docs/project/ — architecture + conventions + flows deep-dives +├── shared/runbooks/ — release-go.md + engineering-standards.md +├── CHANGELOG.md +├── CLAUDE.md — SSoT internals doc +├── PROJECT_SUMMARY.md — this file +├── README.md — user-facing entry doc +├── SECURITY.md +└── .goreleaser.yml — Goreleaser config (CGO multi-arch) ``` -Skipped from the map: `target/`, `.git/`, `.classpath`, `.factorypath`, `.project`, `.settings/`, `node_modules/`, `.dockerignore` — generated, IDE, or noise. - ## Run, build, test -Verified against `.github/workflows/ci-java.yml` (the actual CI gate) and `pom.xml`. +Commands taken from `go/go.mod`, `Makefile` (none — pure `go` tooling), +and `.github/workflows/go-ci.yml`: ```bash -# Build (skipping tests, fastest) -mvn clean package -DskipTests - -# Build + test + spotbugs + dependency-check (the CI gate) -mvn verify +# Install deps (vendored via go module cache; no extra step) +cd go -# Build skipping the npm/Vite frontend (backend-only contributors) -mvn test -Dfrontend.skip=true +# Run unit tests +CGO_ENABLED=1 go test ./... -count=1 -# Skip the OWASP NVD download (~1 GB) on first local run -mvn verify -Ddependency-check.skip=true +# Race detector +CGO_ENABLED=1 go test ./... -race -count=1 -# Run a specific test class -mvn test -Dtest=SpringRestDetectorTest +# Static analysis (mirrors CI) +go install honnef.co/go/tools/cmd/staticcheck@2025.1.1 +staticcheck ./... +go install github.com/securego/gosec/v2/cmd/gosec@v2.22.0 +gosec -quiet -exclude=G104,G115,G202,G204,G301,G304,G306,G401,G404,G501 ./... +go install golang.org/x/vuln/cmd/govulncheck@latest +govulncheck ./... -# Run the pipeline against your code -java -jar target/code-iq-*-cli.jar index /path/to/repo -java -jar target/code-iq-*-cli.jar enrich /path/to/repo -java -jar target/code-iq-*-cli.jar serve /path/to/repo # → http://localhost:8080 +# Build (local) +CGO_ENABLED=1 go build -o /usr/local/bin/codeiq ./cmd/codeiq ``` -CI gate is `mvn verify` — runs unit + integration tests **plus** SpotBugs and OWASP dependency-check executions bound to the `verify` phase (`pom.xml`). `mvn test` alone skips the security gate. See `.github/workflows/ci-java.yml`. - -**Required env / external services:** none. codeiq is offline-first by design — Neo4j and H2 are embedded; no external server, no network calls at runtime. Air-gapped install: `git clone` + Maven mirror + `mvn package`. See [`shared/runbooks/first-time-setup.md`](shared/runbooks/first-time-setup.md). - -**Cache + graph dirs at runtime** (created in your scanned repo): -- `.codeiq/cache/` — H2 incremental analysis cache (`CACHE_VERSION=5` constant near the top of `cache/AnalysisCache.java`; bumped from 4 for the resolver `confidence` + `source` schema, so stale v4 caches drop and rebuild on first run after upgrade) -- `.codeiq/graph/graph.db/` — Neo4j Embedded data dir +**Required env / external services**: none for build. At run-time the +binary reads `OLLAMA_API_KEY` (optional) and `HOMEBREW_TAP_GITHUB_TOKEN` +(release-side only). ## Conventions an agent must respect -(Top 7. Full list in [`docs/project/conventions.md`](docs/project/conventions.md) and [`CLAUDE.md`](CLAUDE.md) §"Critical Rules" / §"Code Conventions".) - -1. **Serving layer is read-only.** No POST/PUT/DELETE on `/api`, no MCP tool that mutates state. All ingestion happens via CLI (`index`, `enrich`). See `api/GraphController.java` (only `@GetMapping`s) and `mcp/McpTools.java`. -2. **Determinism is non-negotiable.** Same input → byte-identical graph. Sort `Set` iterations (`TreeSet` or `stream().sorted()`); detectors must be stateless `@Component` beans; `GraphBuilder` flushes nodes before edges. See `analyzer/GraphBuilder.java`. -3. **Generic detection, not example-specific.** Every detector must work for all languages/frameworks in its scope. Framework detectors (Quarkus, Fastify, etc.) **must** carry discriminator guards requiring framework-specific imports. -4. **Detectors are auto-discovered Spring `@Component` beans** — no registry edits needed. Drop a class in `detector//`, implement `Detector` (or extend an `Abstract*Detector` base class), add a unit test + a determinism test. -5. **Property keys ≥ 3 occurrences become constants.** `private static final String PROP_FRAMEWORK = "framework";` etc. — see existing detectors. -6. **Configuration hierarchy:** built-in defaults → `~/.codeiq/config.yml` → `./codeiq.yml` → `CODEIQ_
_` env → CLI flags. Single source of truth: `codeiq.yml`. Spring-owned keys (e.g. `codeiq.neo4j.enabled`) stay in `application.yml`. See [`docs/codeiq.yml.example`](docs/codeiq.yml.example) and `CLAUDE.md` §"Configuration". -7. **Air-gapped build target.** No public-internet calls at runtime, all assets bundled local, vendored where possible. Per-org rule in [`shared/runbooks/engineering-standards.md`](shared/runbooks/engineering-standards.md) §7 and [`~/.claude/rules/build.md`](~/.claude/rules/build.md). +- **Detector blank-import**: new package under `internal/detector//` + must be added to `internal/cli/detectors_register.go`. The polyglot + benchmark caught 15 missing imports (commit `04098be`). +- **Determinism**: never iterate a Go `map` without sorting keys. Run + the determinism test twice with the same fixture and assert byte + equality. +- **Anchor nodes for cross-file edges**: use + `base.EnsureFileAnchor` + `base.EnsureExternalAnchor`. Otherwise + imports/depends_on edges drop at Snapshot's phantom filter. +- **Read-only MCP**: every MCP tool reads. `run_cypher` rejects + mutation keywords. `review_changes` reads the graph + shells `git` + read-only. +- **Confidence + Source mandatory**: every emitted `CodeNode` and + `CodeEdge`. Base classes stamp the floor at the orchestration + boundary; detectors override only when they have higher-confidence + evidence. + +Full set in [`CLAUDE.md` §Code Conventions](CLAUDE.md#code-conventions) +and [`docs/project/conventions.md`](docs/project/conventions.md). ## Gotchas -(Top items. Full list in [`CLAUDE.md`](CLAUDE.md) §"Gotchas & Lessons Learned" — that section is canonical and longer; cross-reference to it.) - -- **Pipeline order is `index → enrich → serve`.** Don't put analysis in `serve`; it's read-only. `serve` requires a prior `enrich` for a populated Neo4j directory. -- **Neo4j property round-trip uses `prop_*` keys.** Properties are written by `bulkSave` (UNWIND Cypher) with a `prop_` prefix and restored by `nodeFromNeo4j()` in `graph/GraphStore.java`. If you add a new property, verify it survives write→read. -- **Edges must be attached to source nodes before `bulkSave()`.** Cypher `MATCH` silently returns 0 rows for missing source IDs — pre-validate. -- **`@ActiveProfiles("test")` is required on every `@SpringBootTest`** to avoid Neo4j auto-startup conflicts. -- **`AnalysisCache` uses a `ReentrantReadWriteLock`** (not `synchronized`). JEP 491 (Java 25) means lock primitives no longer pin virtual-thread carriers; the read/write lock is what prevents `ClosedChannelException` on H2's MVStore under concurrent virtual-thread access. Don't "simplify" to `synchronized`. -- **Bump `CACHE_VERSION` in `cache/AnalysisCache.java`** (top of file) when you change the file-hash algorithm or H2 schema. Stale caches auto-clear on next run. Currently `5` (bumped from 4 for the resolver `confidence` + `source` schema). -- **Symbol resolver is index-time only.** `Analyzer.bootstrapResolvers()` is reached from `run` / `runBatchedIndex` / `runSmartIndex` only — never at `serve`. The SPI lives at `intelligence/resolver/`; the Java backend wraps `javaparser-symbol-solver-core`. RESOLVED-tier edges and `target_fqn` properties land at index-time and are then served read-only from Neo4j. -- **`JavaSymbolResolver.resolve(String)` enforces strict parse-success.** Partial-CU outputs from JavaParser problems are converted to `EmptyResolved` so the graph never carries phantom RESOLVED edges from broken parses. Detectors must handle `EmptyResolved` as "lexical fallback". -- **SnakeYAML parses bare `on` as `Boolean.TRUE`.** Compare YAML keys with `String.valueOf(key)`, not `Boolean.TRUE.equals(key)` (SonarCloud S2159). -- **Determinism gate:** every new detector needs a determinism test (run twice, assert equal output) — see existing `*DetectorTest.java` for the pattern. -- **First `mvn verify` downloads ~1 GB NVD database** for OWASP dependency-check. Override locally with `-Ddependency-check.skip=true`. -- **Live counts (verified 2026-04-27):** **99 concrete detectors** (excluding `Abstract*` and `*Helper*`), **34 `NodeKind` values**, **28 `EdgeKind` values**, **236 test files / 3,270 test methods**. `CLAUDE.md`, `README.md`, and the source javadocs are in sync. When adding a `NodeKind` / `EdgeKind` / detector, update the count in the source javadoc, `CLAUDE.md` (intro + package summary + key-files table), `README.md` (intro + mermaid subgraph), and this file in the same PR — drift is the default if you don't. -- **Don't merge anything that fails `mvn verify`.** SpotBugs + dependency-check + tests are bound to `verify`, not `test`. +- **Kuzu v0.7.1 binder limitations** — no FTS, no parameterized + LIMIT/SKIP, `lower()` not `toLower()`, no negative lookahead, list + comprehensions reject out-of-scope variables. See + [`CLAUDE.md` §Kuzu v0.7.1 quirks](CLAUDE.md#kuzu-v071-quirks). +- **Go RE2 vs Java regex** — no lookahead, no possessive quantifiers. + Strip `*+` when porting; use two-stage matchers for lookahead. +- **MCP SDK v1.6** — `Server.AddTool(t, h)` (two args, not aggregate). + `StdioTransport{}` zero-value, no factory. JSON marshal of string + returns needs special casing in `mcp/tool.go`. +- **`detectors_register.go` is a choke point** — see above. +- **gosec @v2.21.4 fails to build under Go 1.25** — pinned to v2.22.0. +- **GO-2026-4918 (HTTP/2 SETTINGS DoS)** reachable from + `review.Client.Review` — fixed in Go 1.25.10 (our toolchain pin). ## Where to look next -- **Architecture & components** → [`docs/project/architecture.md`](docs/project/architecture.md) -- **Data model (Node/Edge kinds, Neo4j schema, H2 cache)** → [`docs/project/data-model.md`](docs/project/data-model.md) -- **UI (React SPA, Vite, page hierarchy)** → [`docs/project/ui.md`](docs/project/ui.md) -- **Key flows (index→enrich→serve, MCP tool lifecycle)** → [`docs/project/flows.md`](docs/project/flows.md) -- **Conventions (full)** → [`docs/project/conventions.md`](docs/project/conventions.md) -- **Build & run details (Maven phases, ANTLR codegen, frontend embed)** → [`docs/project/build-and-run.md`](docs/project/build-and-run.md) -- **Active design specs (in-flight architectural work)** → [`docs/specs/`](docs/specs/) — currently: sub-project 1 (resolver SPI + Java pilot + confidence schema) -- **Internal canonical reference (hand-maintained)** → [`CLAUDE.md`](CLAUDE.md) -- **Engineering standards / release / rollback** → [`shared/runbooks/`](shared/runbooks/) - -(Skipped: `docs/project/integrations.md` — codeiq makes no runtime calls to external APIs / queues. The `docs/codeiq.yml.example` schema and `shared/runbooks/release.md` cover what little external surface exists at build/release time.) +- Architecture & components → [`docs/project/architecture.md`](docs/project/architecture.md) +- Conventions (full) → [`docs/project/conventions.md`](docs/project/conventions.md) +- Build & release → [`shared/runbooks/release-go.md`](shared/runbooks/release-go.md) +- MCP integration → [`README.md#mcp-integration`](README.md#mcp-integration) +- Internal SSoT → [`CLAUDE.md`](CLAUDE.md) diff --git a/README.md b/README.md index 0528bd1d..656f3a5d 100644 --- a/README.md +++ b/README.md @@ -1,311 +1,181 @@

codeiq

- Deterministic code knowledge graph -- scans codebases to map services, endpoints, entities, infrastructure, auth patterns, and framework usage. No AI, pure static analysis. + Deterministic code knowledge graph — scans codebases to map services, endpoints, entities, infrastructure, auth patterns, and framework usage. No AI, pure static analysis. Single static Go binary; MCP server included.

- Maven Central - CI - Java 25 - MIT License - Security (OSV-Scanner + Trivy + Semgrep + Gitleaks + jscpd + SBOM) + Latest release + CI + Go 1.25.10 + License + Security OpenSSF Scorecard OpenSSF Best Practices - 97 Detectors + 100 Detectors 35+ Languages

--- -## Development — Go Port (Phase 1) +## What it is -An in-progress Go port lives in [`go/`](./go/). Phase 1 ships `codeiq index` -over 5 detectors with byte-level parity against the Java side on -`go/testdata/fixture-minimal`. Phases 2-6 land enrich, MCP, the remaining 94 -detectors, release infra, and Java cutover (see -[`docs/superpowers/specs/2026-05-11-codeiq-go-port-design.md`](docs/superpowers/specs/2026-05-11-codeiq-go-port-design.md)). +codeiq scans a codebase and produces a deterministic graph of its +services, endpoints, entities, infrastructure, auth patterns, and +framework usage. Same input ⇒ same output, every time. -Build and run: +- **Single static binary** — built from the `go/` tree. No JVM, no + Spring Boot start time. ~30 MB. CGO enabled (Kuzu graph + SQLite + cache). +- **100 detectors** across 35+ languages — Java, Kotlin, Scala, Python, + TypeScript/JavaScript, Go, Rust, C#, C++, Terraform, Bicep, Helm, + Kubernetes, Docker, GitHub Actions, GitLab CI, … +- **MCP server included** — `codeiq mcp` runs an MCP stdio server with + 6 consolidated mode-driven tools (plus 34 deprecated narrow tools for + back-compat) so Claude / Cursor / any MCP-aware agent can query the + graph directly. +- **LLM-driven PR review** — `codeiq review` walks the diff, queries + the indexed graph for evidence, and asks Ollama (Cloud or local) for + review comments. -```bash -cd go -CGO_ENABLED=1 go build -o codeiq ./cmd/codeiq -./codeiq index . -./codeiq --version -``` +## Install -The Go binary writes to the same `.codeiq/cache/` location the Java side -uses, but `CACHE_VERSION` is bumped to 6 so the first run triggers a clean -rebuild. Phase 1 is parity-only — use the Java side for production runs. +### Pre-built binary -## Quick Start +Grab from +[Releases](https://github.com/RandomCodeSpace/codeiq/releases/latest): ```bash -# Build from source (requires Java 25+, Maven 3.9+) -git clone https://github.com/RandomCodeSpace/codeiq.git -cd codeiq -mvn clean package -DskipTests - -# Analyze a codebase -java -jar target/code-iq-*-cli.jar analyze /path/to/repo - -# Start server (REST API + MCP + React UI) -java -jar target/code-iq-*-cli.jar serve /path/to/repo -# Open http://localhost:8080 +curl -L https://github.com/RandomCodeSpace/codeiq/releases/latest/download/codeiq_$(uname -s | tr A-Z a-z)_$(uname -m | sed s/x86_64/amd64/).tar.gz | tar xz +sudo install codeiq /usr/local/bin/ +codeiq --version ``` -## How It Works - -codeiq scans source files using 99 detectors across 35+ languages, builds a knowledge graph of code relationships, and serves it via REST API, MCP server, and React UI. - -```mermaid -graph TD - subgraph "1. Index" - A[File Discovery] -->|git ls-files| B[Parsing Layer] - B -->|JavaParser / ANTLR / Regex| C[99 Detectors] - C -->|Virtual Threads| D[Graph Builder] - D --> E[(H2 Cache)] - end - - subgraph "2. Enrich" - E --> F[Neo4j Bulk Load] - F --> G[Cross-file Linkers] - G --> H[Layer Classifier] - H --> I[Service Detector] - I --> J[(Neo4j Graph)] - end - - subgraph "3. Serve" - J --> K[REST API - 37 endpoints] - J --> L[MCP Server - 34 tools] - J --> M[React UI - 4 pages] - end -``` - -### Three-Command Pipeline - -For large codebases or memory-constrained environments: +Verify (Sigstore keyless): ```bash -# 1. Index: batched H2 streaming, low memory (~1-2GB for 20K files) -java -jar code-iq-*-cli.jar index /path/to/repo --batch-size 500 - -# 2. Enrich: load H2 into Neo4j, run linkers + classifier + topology -java -jar code-iq-*-cli.jar enrich /path/to/repo - -# 3. Serve: REST API + MCP + React UI -java -jar code-iq-*-cli.jar serve /path/to/repo +sha256sum -c checksums.sha256 +cosign verify-blob \ + --certificate checksums.sha256.pem \ + --signature checksums.sha256.sig \ + --certificate-identity-regexp 'https://github.com/RandomCodeSpace/codeiq/.github/workflows/release-go.yml@.*' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + checksums.sha256 ``` -For small codebases, `analyze` does everything in one step: +### Homebrew ```bash -java -jar code-iq-*-cli.jar analyze /path/to/repo +brew tap RandomCodeSpace/codeiq +brew install codeiq ``` -## CLI Commands - -| Command | Description | -|---------|-------------| -| `analyze [path]` | Scan and build knowledge graph (in-memory, all-in-one) | -| `index [path]` | Memory-efficient batched indexing to H2 | -| `enrich [path]` | Load H2 into Neo4j with linkers + classifier + topology | -| `serve [path]` | Start React UI + REST API + MCP server | -| `stats [path]` | Rich categorized statistics | -| `graph [path]` | Export graph (JSON, YAML, Mermaid, DOT) | -| `query [path]` | Query relationships (consumers, producers, callers) | -| `find [what] [path]` | Preset queries (endpoints, guards, entities, topics) | -| `cypher [query]` | Execute raw Cypher queries against Neo4j | -| `topology [path]` | Service topology (blast radius, circular deps, bottlenecks) | -| `flow [path]` | Architecture flow diagrams | -| `bundle [path]` | Package graph + source into distributable ZIP | -| `cache [action]` | Manage analysis cache | -| `plugins [action]` | List/inspect detectors, suggest config | -| `version` | Show version info | - -## Server +### Build from source -```bash -java -jar target/code-iq-*-cli.jar serve /path/to/repo --port 8080 -``` - -```mermaid -graph LR - subgraph "http://localhost:8080" - A["/ React UI"] --- B["/api REST API"] - B --- C["/mcp MCP Server"] - end -``` - -| Interface | Description | -|-----------|-------------| -| **React UI** (`/`) | Dashboard (stats + charts), Codebase Map (ECharts treemap), Explorer (node browser), MCP Console (tool invocationgrams, MCP Console, API Docs | -| **REST API** (`/api`) | 37 endpoints -- stats, nodes, edges, topology, triage, search, flow | -| **MCP Server** (`/mcp`) | 34 tools via Spring AI streamable HTTP for AI-powered code triage | - -## Supported Frameworks - -| Language | Frameworks & Patterns | -|----------|----------------------| -| **Java** | Spring REST, Spring Security, JPA/Hibernate, Kafka, RabbitMQ, JMS, gRPC, JAX-RS, WebSocket, Quarkus, Micronaut | -| **Python** | Flask, Django (views + models + auth), FastAPI (routes + auth), SQLAlchemy, Celery, Pydantic | -| **TypeScript** | Express, NestJS, Fastify, Remix, GraphQL, TypeORM, Prisma, Sequelize, Mongoose, KafkaJS, Passport/JWT | -| **Frontend** | React, Vue, Angular, Svelte components and routes | -| **Go** | Gin, Echo, Chi, gorilla/mux, net/http, GORM, sqlx | -| **C#** | Entity Framework Core, Minimal APIs, ASP.NET Core | -| **Rust** | Actix-web, Axum | -| **Kotlin** | Ktor routes | -| **Infra** | Terraform, Kubernetes, Docker Compose, Dockerfile, Bicep, Helm, GitHub Actions, GitLab CI, CloudFormation | -| **Auth** | Spring Security, Django Auth, FastAPI Auth, NestJS Guards, Passport/JWT, K8s RBAC, LDAP | - -## Service Topology - -AppDynamics-style service topology from static code analysis: +Requires Go 1.25.10+ and a C toolchain (CGO). ```bash -# View service topology -java -jar code-iq-*-cli.jar topology /path/to/monorepo - -# Blast radius analysis -java -jar code-iq-*-cli.jar topology /path/to/repo --blast-radius service-name - -# Multi-repo support -java -jar code-iq-*-cli.jar index /repo1 --graph /shared --service-name frontend -java -jar code-iq-*-cli.jar index /repo2 --graph /shared --service-name backend -java -jar code-iq-*-cli.jar serve /shared +git clone https://github.com/RandomCodeSpace/codeiq.git +cd codeiq/go +CGO_ENABLED=1 go build -o /usr/local/bin/codeiq ./cmd/codeiq +codeiq --version ``` -## Configuration - -codeiq is configured by a single YAML file at the repo root: **`codeiq.yml`**. -Every field is optional; omitted fields fall back to the in-code defaults -(`ConfigDefaults.builtIn()`). See -[`docs/codeiq.yml.example`](docs/codeiq.yml.example) for the full reference -with inline documentation. All keys are **snake_case**; camelCase spellings -are accepted as deprecated aliases for one release and log a WARN on load. - -### Resolution order (last wins) - -1. Built-in defaults -2. `~/.codeiq/config.yml` (user-global) -3. `./codeiq.yml` (project) -4. Environment variables: `CODEIQ_
_` (e.g. `CODEIQ_SERVING_PORT=9090`, - `CODEIQ_MCP_AUTH_MODE=bearer`, `CODEIQ_INDEXING_BATCH_SIZE=1000`). Nested - keys are flattened with underscores; values parse as YAML scalars. -5. CLI flags on `codeiq ` - -### Commands +## Quickstart ```bash -codeiq config validate # Validate ./codeiq.yml, exit 1 on error -codeiq config validate -p custom.yml -codeiq config explain # Print each effective value + its source layer -``` +# Index a repository → SQLite analysis cache. +codeiq index /path/to/repo -### Minimal example +# Enrich → Kuzu graph at .codeiq/graph/codeiq.kuzu. +codeiq enrich /path/to/repo -```yaml -project: - name: my-service - root: . +# Query. +codeiq stats /path/to/repo +codeiq find endpoints /path/to/repo +codeiq query consumers /path/to/repo +codeiq topology /path/to/repo +codeiq flow /path/to/repo --view overview --format mermaid -indexing: - exclude: ['**/node_modules/**', '**/build/**', '**/dist/**'] - cache_dir: .codeiq/cache - batch_size: 500 - -serving: - port: 8080 - bind_address: 0.0.0.0 - -mcp: - enabled: true - transport: http +# LLM PR review (local Ollama; OLLAMA_API_KEY → Cloud). +codeiq review --base origin/main --head HEAD /path/to/repo ``` -### Spring-owned keys (stay in `application.yml`) - -A handful of keys drive Spring's `@ConditionalOnProperty` / `@Value` wiring -and have not been migrated into `codeiq.yml`. Keep them in -`src/main/resources/application.yml`: - -- `codeiq.neo4j.enabled` -- profile-conditional Neo4j toggle (`false` under - the `indexing` profile, `true` under `serving`). -- `codeiq.neo4j.bolt.port` -- embedded Neo4j Bolt listener port. -- `codeiq.cors.allowed-origin-patterns` -- CORS allow-list for the REST API. -- `codeiq.ui.enabled` -- toggles the React SPA static resource handler. - -Everything else belongs in `codeiq.yml`. `UnifiedConfigBeans` bridges the -two worlds for values that exist in both. - -See `docs/codeiq.yml.example` for the full schema. - -## Graph Model - -```mermaid -graph LR - subgraph "Node Types (34)" - direction TB - N1[service] --- N2[endpoint] - N2 --- N3[class] - N3 --- N4[method] - N4 --- N5[entity] - N5 --- N6[topic / queue] - N6 --- N7[guard / middleware] - N7 --- N8[config_file] - end - - subgraph "Edge Types (28)" - direction TB - E1[calls] --- E2[imports] - E2 --- E3[depends_on] - E3 --- E4[produces / consumes] - E4 --- E5[queries / connects_to] - E5 --- E6[extends / implements] - E6 --- E7[protects / contains] - end -``` - -## Benchmarks - -| Project | Files | Nodes | Edges | Time | -|---------|-------|-------|-------|------| -| kubernetes | 20,240 | 193,391 | 349,707 | 9s | -| kafka | 6,919 | 62,692 | 120,422 | 50s | -| django | 3,467 | 51,402 | 99,086 | 54s | -| spring-boot | 10,524 | 27,993 | 39,776 | 27s | -| fastapi | 2,740 | 25,475 | 30,430 | 10s | -| nest | 2,037 | 5,757 | 11,904 | 1s | +## MCP integration -All results are 100% deterministic across runs. +Add to your MCP client config (e.g. `.mcp.json` at the project root): -## Development - -```bash -git clone https://github.com/RandomCodeSpace/codeiq.git -cd codeiq -mvn clean package # Build + test (3,270 tests across 236 files) -mvn test # Tests only +```json +{ + "mcpServers": { + "code-mcp": { + "command": "codeiq", + "args": ["mcp"] + } + } +} ``` -### Maven Dependency - -```xml - - io.github.randomcodespace.iq - code-iq - 0.0.1-beta.0 - -``` +Six mode-driven tools (`graph_summary`, `find_in_graph`, `inspect_node`, +`trace_relationships`, `analyze_impact`, `topology_view`) plus +`run_cypher` (escape hatch) and `review_changes` (in-agent PR review). +The deprecated 34 narrow tools remain wired for one release for +back-compat. + +## CLI reference + +| Command | Purpose | +|---|---| +| `index [path]` | Scan files → SQLite analysis cache. | +| `enrich [path]` | Load cache → Kuzu graph; run linkers + layer classifier. | +| `mcp [path]` | Stdio MCP server (Claude / Cursor). | +| `stats [path]` | Categorized statistics. | +| `query [path]` | consumers / producers / callers / dependencies / dependents / shortest-path / cycles / dead-code. | +| `find [path]` | endpoints, entities, services, … | +| `cypher [path]` | Raw Cypher against Kuzu (read-only). | +| `flow [path]` | Mermaid / dot / yaml flow diagrams. | +| `graph [path]` | Export graph: json / yaml / mermaid / dot. | +| `topology [path]` | Service-topology projection. | +| `review [path]` | LLM-driven PR review. | +| `cache ` | Inspect / clear the analysis cache. | +| `plugins ` | List + describe registered detectors. | +| `config ` | Validate / explain `codeiq.yml`. | +| `version` | Build info. | + +`codeiq --help` for full flag listing. + +## Design + +The graph is canonical and deterministic — `GraphBuilder` deduplicates +nodes by ID (confidence-aware merge) and edges by canonical +`(source, target, kind)` tuple. Phantom edges (endpoint missing from +the graph) are dropped at snapshot. Every run prints a +"Deduped: N nodes, M edges Dropped: K phantom edges" line so graph +hygiene is visible. + +See [`docs/project/architecture.md`](docs/project/architecture.md) for +the pipeline (FileDiscovery → tree-sitter / regex → detectors → +GraphBuilder → linkers → LayerClassifier → Kuzu) and +[`docs/project/conventions.md`](docs/project/conventions.md) for the +detector authoring contract. + +## Releases + +Tag `vX.Y.Z` → `.github/workflows/release-go.yml` builds linux/amd64, +linux/arm64, darwin/arm64 archives with SPDX SBOMs (Syft); the +checksum manifest is keyless-signed via Cosign + GitHub OIDC +(Sigstore Rekor). Runbook: +[`shared/runbooks/release-go.md`](shared/runbooks/release-go.md). + +## Security + +See [SECURITY.md](SECURITY.md). Supply-chain stack: OpenSSF Best +Practices [12650](https://www.bestpractices.dev/projects/12650), +OpenSSF Scorecard, and the OSS-CLI workflow +([`security.yml`](.github/workflows/security.yml)) running OSV-Scanner, +Trivy, Semgrep, Gitleaks, jscpd, and `anchore/sbom-action` on every PR. ## License -MIT License. See [LICENSE](LICENSE) for details. - ---- - -

- Built with intelligence. No AI required. -

+See [LICENSE](LICENSE). diff --git a/pom.xml b/pom.xml deleted file mode 100644 index a5867da9..00000000 --- a/pom.xml +++ /dev/null @@ -1,643 +0,0 @@ - - - 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 4.0.6 - - - - io.github.randomcodespace.iq - code-iq - 0.1.0-SNAPSHOT - jar - - codeiq - CLI tool and server that scans codebases to build a deterministic code knowledge graph - https://github.com/RandomCodeSpace/codeiq - - - 25 - 2026.04.0 - 2.0.0-M4 - 4.7.7 - 0.8.14 - 4.9.8.3 - 3.6.0 - - - false - - - 11.0.21 - 3.1.1 - - - - - - org.springframework.ai - spring-ai-bom - ${spring-ai.version} - pom - import - - - - - org.apache.logging.log4j - log4j-core - 2.25.4 - - - org.apache.logging.log4j - log4j-api - 2.25.4 - - - org.apache.logging.log4j - log4j-layout-template-json - 2.25.4 - - - org.apache.shiro - shiro-core - 2.1.0 - - - io.modelcontextprotocol.sdk - mcp-core - 1.1.2 - - - - - tools.jackson.core - jackson-core - 3.1.2 - - - tools.jackson.core - jackson-databind - 3.1.2 - - - tools.jackson.core - jackson-annotations - 3.1.1 - - - - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-data-neo4j - - - org.springframework.boot - spring-boot-starter-cache - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-security - - - - - com.bucket4j - bucket4j_jdk17-core - 8.18.0 - - - - - com.github.ben-manes.caffeine - caffeine - - - - - net.logstash.logback - logstash-logback-encoder - 9.0 - - - - - io.micrometer - micrometer-registry-prometheus - - - - - org.neo4j - neo4j - ${neo4j.version} - - - - org.neo4j - neo4j-slf4j-provider - - - - - - - org.springframework.ai - spring-ai-starter-mcp-server-webmvc - - - - - info.picocli - picocli-spring-boot-starter - ${picocli.version} - - - info.picocli - picocli - ${picocli.version} - - - - - com.github.javaparser - javaparser-core - 3.28.0 - - - - - com.github.javaparser - javaparser-symbol-solver-core - 3.28.0 - - - - - org.antlr - antlr4-runtime - 4.13.2 - - - - - com.h2database - h2 - - - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - 3.0.3 - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - MIT License - https://opensource.org/licenses/MIT - - - - - - RandomCodeSpace - https://github.com/RandomCodeSpace - - - - - scm:git:git://github.com/RandomCodeSpace/codeiq.git - scm:git:ssh://github.com:RandomCodeSpace/codeiq.git - https://github.com/RandomCodeSpace/codeiq/tree/main - - - - - - - com.github.eirslett - frontend-maven-plugin - 2.0.0 - - src/main/frontend - - v22.12.0 - ${frontend.skip} - - - - install-node-npm - install-node-and-npm - - - npm-install - npm - - install - - - - npm-build - npm - - run build - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - cli - - - - - build-info - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${java.version} - - - - - org.antlr - antlr4-maven-plugin - 4.13.2 - - - antlr4 - - - - true - true - false - - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - enforce-java - - enforce - - - - - [25,) - Java 25 or later is required. - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - -XX:+EnableDynamicAgentLoading @{argLine} - - **/benchmark/** - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - -XX:+EnableDynamicAgentLoading @{argLine} - - - - - integration-test - verify - - - - - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - - io/github/randomcodespace/iq/grammar/** - - - - - prepare-agent - - prepare-agent - - - - report - test - - report - - - - check - verify - - check - - - - - BUNDLE - - - LINE - COVEREDRATIO - 0.85 - - - - - - - - - - - com.github.spotbugs - spotbugs-maven-plugin - ${spotbugs.version} - - spotbugs-exclude.xml - - High - true - - - - - spotbugs-check-on-verify - verify - - check - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - ${checkstyle-plugin.version} - - google_checks.xml - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - src/assembly/source-bundle.xml - - ${project.artifactId}-${project.version} - true - - - - create-source-bundle - package - - single - - - - - - - - - - - - mutation - - - - org.pitest - pitest-maven - 1.18.0 - - - io.github.randomcodespace.iq.intelligence.resolver.* - io.github.randomcodespace.iq.intelligence.resolver.java.* - io.github.randomcodespace.iq.model.Confidence - - - io.github.randomcodespace.iq.intelligence.resolver.* - io.github.randomcodespace.iq.intelligence.resolver.java.* - io.github.randomcodespace.iq.model.ConfidenceTest - - - HTML - XML - - false - - - - - - - release - - - - - org.sonatype.central - central-publishing-maven-plugin - 0.10.0 - true - - central - true - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - none - - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.2.8 - - - sign-artifacts - verify - - sign - - - - - - - - - diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml deleted file mode 100644 index b97f611d..00000000 --- a/spotbugs-exclude.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/assembly/source-bundle.xml b/src/assembly/source-bundle.xml deleted file mode 100644 index a06dd699..00000000 --- a/src/assembly/source-bundle.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - source-bundle - - zip - tar.gz - - - true - ${project.artifactId}-${project.version} - - - - - ${project.basedir} - / - - pom.xml - README.md - CLAUDE.md - LICENSE - .gitignore - sonar-project.properties - - - - - - ${project.basedir}/src - /src - - **/* - - - - main/frontend/node_modules/** - main/frontend/node/** - main/frontend/dist/** - main/frontend/.cache/** - main/frontend/tsconfig.tsbuildinfo - - **/grammar/**/generated/** - - - - - - ${project.basedir}/.github - /.github - - **/* - - - - - diff --git a/src/main/antlr4/imports/UnicodeClasses.g4 b/src/main/antlr4/imports/UnicodeClasses.g4 deleted file mode 100644 index 642a8b79..00000000 --- a/src/main/antlr4/imports/UnicodeClasses.g4 +++ /dev/null @@ -1,1656 +0,0 @@ -/** - * Taken from http://www.antlr3.org/grammar/1345144569663/AntlrUnicode.txt - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar UnicodeClasses; - -UNICODE_CLASS_LL: - '\u0061' ..'\u007A' - | '\u00B5' - | '\u00DF' ..'\u00F6' - | '\u00F8' ..'\u00FF' - | '\u0101' - | '\u0103' - | '\u0105' - | '\u0107' - | '\u0109' - | '\u010B' - | '\u010D' - | '\u010F' - | '\u0111' - | '\u0113' - | '\u0115' - | '\u0117' - | '\u0119' - | '\u011B' - | '\u011D' - | '\u011F' - | '\u0121' - | '\u0123' - | '\u0125' - | '\u0127' - | '\u0129' - | '\u012B' - | '\u012D' - | '\u012F' - | '\u0131' - | '\u0133' - | '\u0135' - | '\u0137' - | '\u0138' - | '\u013A' - | '\u013C' - | '\u013E' - | '\u0140' - | '\u0142' - | '\u0144' - | '\u0146' - | '\u0148' - | '\u0149' - | '\u014B' - | '\u014D' - | '\u014F' - | '\u0151' - | '\u0153' - | '\u0155' - | '\u0157' - | '\u0159' - | '\u015B' - | '\u015D' - | '\u015F' - | '\u0161' - | '\u0163' - | '\u0165' - | '\u0167' - | '\u0169' - | '\u016B' - | '\u016D' - | '\u016F' - | '\u0171' - | '\u0173' - | '\u0175' - | '\u0177' - | '\u017A' - | '\u017C' - | '\u017E' ..'\u0180' - | '\u0183' - | '\u0185' - | '\u0188' - | '\u018C' - | '\u018D' - | '\u0192' - | '\u0195' - | '\u0199' ..'\u019B' - | '\u019E' - | '\u01A1' - | '\u01A3' - | '\u01A5' - | '\u01A8' - | '\u01AA' - | '\u01AB' - | '\u01AD' - | '\u01B0' - | '\u01B4' - | '\u01B6' - | '\u01B9' - | '\u01BA' - | '\u01BD' ..'\u01BF' - | '\u01C6' - | '\u01C9' - | '\u01CC' - | '\u01CE' - | '\u01D0' - | '\u01D2' - | '\u01D4' - | '\u01D6' - | '\u01D8' - | '\u01DA' - | '\u01DC' - | '\u01DD' - | '\u01DF' - | '\u01E1' - | '\u01E3' - | '\u01E5' - | '\u01E7' - | '\u01E9' - | '\u01EB' - | '\u01ED' - | '\u01EF' - | '\u01F0' - | '\u01F3' - | '\u01F5' - | '\u01F9' - | '\u01FB' - | '\u01FD' - | '\u01FF' - | '\u0201' - | '\u0203' - | '\u0205' - | '\u0207' - | '\u0209' - | '\u020B' - | '\u020D' - | '\u020F' - | '\u0211' - | '\u0213' - | '\u0215' - | '\u0217' - | '\u0219' - | '\u021B' - | '\u021D' - | '\u021F' - | '\u0221' - | '\u0223' - | '\u0225' - | '\u0227' - | '\u0229' - | '\u022B' - | '\u022D' - | '\u022F' - | '\u0231' - | '\u0233' ..'\u0239' - | '\u023C' - | '\u023F' - | '\u0240' - | '\u0242' - | '\u0247' - | '\u0249' - | '\u024B' - | '\u024D' - | '\u024F' ..'\u0293' - | '\u0295' ..'\u02AF' - | '\u0371' - | '\u0373' - | '\u0377' - | '\u037B' ..'\u037D' - | '\u0390' - | '\u03AC' ..'\u03CE' - | '\u03D0' - | '\u03D1' - | '\u03D5' ..'\u03D7' - | '\u03D9' - | '\u03DB' - | '\u03DD' - | '\u03DF' - | '\u03E1' - | '\u03E3' - | '\u03E5' - | '\u03E7' - | '\u03E9' - | '\u03EB' - | '\u03ED' - | '\u03EF' ..'\u03F3' - | '\u03F5' - | '\u03F8' - | '\u03FB' - | '\u03FC' - | '\u0430' ..'\u045F' - | '\u0461' - | '\u0463' - | '\u0465' - | '\u0467' - | '\u0469' - | '\u046B' - | '\u046D' - | '\u046F' - | '\u0471' - | '\u0473' - | '\u0475' - | '\u0477' - | '\u0479' - | '\u047B' - | '\u047D' - | '\u047F' - | '\u0481' - | '\u048B' - | '\u048D' - | '\u048F' - | '\u0491' - | '\u0493' - | '\u0495' - | '\u0497' - | '\u0499' - | '\u049B' - | '\u049D' - | '\u049F' - | '\u04A1' - | '\u04A3' - | '\u04A5' - | '\u04A7' - | '\u04A9' - | '\u04AB' - | '\u04AD' - | '\u04AF' - | '\u04B1' - | '\u04B3' - | '\u04B5' - | '\u04B7' - | '\u04B9' - | '\u04BB' - | '\u04BD' - | '\u04BF' - | '\u04C2' - | '\u04C4' - | '\u04C6' - | '\u04C8' - | '\u04CA' - | '\u04CC' - | '\u04CE' - | '\u04CF' - | '\u04D1' - | '\u04D3' - | '\u04D5' - | '\u04D7' - | '\u04D9' - | '\u04DB' - | '\u04DD' - | '\u04DF' - | '\u04E1' - | '\u04E3' - | '\u04E5' - | '\u04E7' - | '\u04E9' - | '\u04EB' - | '\u04ED' - | '\u04EF' - | '\u04F1' - | '\u04F3' - | '\u04F5' - | '\u04F7' - | '\u04F9' - | '\u04FB' - | '\u04FD' - | '\u04FF' - | '\u0501' - | '\u0503' - | '\u0505' - | '\u0507' - | '\u0509' - | '\u050B' - | '\u050D' - | '\u050F' - | '\u0511' - | '\u0513' - | '\u0515' - | '\u0517' - | '\u0519' - | '\u051B' - | '\u051D' - | '\u051F' - | '\u0521' - | '\u0523' - | '\u0525' - | '\u0527' - | '\u0561' ..'\u0587' - | '\u1D00' ..'\u1D2B' - | '\u1D6B' ..'\u1D77' - | '\u1D79' ..'\u1D9A' - | '\u1E01' - | '\u1E03' - | '\u1E05' - | '\u1E07' - | '\u1E09' - | '\u1E0B' - | '\u1E0D' - | '\u1E0F' - | '\u1E11' - | '\u1E13' - | '\u1E15' - | '\u1E17' - | '\u1E19' - | '\u1E1B' - | '\u1E1D' - | '\u1E1F' - | '\u1E21' - | '\u1E23' - | '\u1E25' - | '\u1E27' - | '\u1E29' - | '\u1E2B' - | '\u1E2D' - | '\u1E2F' - | '\u1E31' - | '\u1E33' - | '\u1E35' - | '\u1E37' - | '\u1E39' - | '\u1E3B' - | '\u1E3D' - | '\u1E3F' - | '\u1E41' - | '\u1E43' - | '\u1E45' - | '\u1E47' - | '\u1E49' - | '\u1E4B' - | '\u1E4D' - | '\u1E4F' - | '\u1E51' - | '\u1E53' - | '\u1E55' - | '\u1E57' - | '\u1E59' - | '\u1E5B' - | '\u1E5D' - | '\u1E5F' - | '\u1E61' - | '\u1E63' - | '\u1E65' - | '\u1E67' - | '\u1E69' - | '\u1E6B' - | '\u1E6D' - | '\u1E6F' - | '\u1E71' - | '\u1E73' - | '\u1E75' - | '\u1E77' - | '\u1E79' - | '\u1E7B' - | '\u1E7D' - | '\u1E7F' - | '\u1E81' - | '\u1E83' - | '\u1E85' - | '\u1E87' - | '\u1E89' - | '\u1E8B' - | '\u1E8D' - | '\u1E8F' - | '\u1E91' - | '\u1E93' - | '\u1E95' ..'\u1E9D' - | '\u1E9F' - | '\u1EA1' - | '\u1EA3' - | '\u1EA5' - | '\u1EA7' - | '\u1EA9' - | '\u1EAB' - | '\u1EAD' - | '\u1EAF' - | '\u1EB1' - | '\u1EB3' - | '\u1EB5' - | '\u1EB7' - | '\u1EB9' - | '\u1EBB' - | '\u1EBD' - | '\u1EBF' - | '\u1EC1' - | '\u1EC3' - | '\u1EC5' - | '\u1EC7' - | '\u1EC9' - | '\u1ECB' - | '\u1ECD' - | '\u1ECF' - | '\u1ED1' - | '\u1ED3' - | '\u1ED5' - | '\u1ED7' - | '\u1ED9' - | '\u1EDB' - | '\u1EDD' - | '\u1EDF' - | '\u1EE1' - | '\u1EE3' - | '\u1EE5' - | '\u1EE7' - | '\u1EE9' - | '\u1EEB' - | '\u1EED' - | '\u1EEF' - | '\u1EF1' - | '\u1EF3' - | '\u1EF5' - | '\u1EF7' - | '\u1EF9' - | '\u1EFB' - | '\u1EFD' - | '\u1EFF' ..'\u1F07' - | '\u1F10' ..'\u1F15' - | '\u1F20' ..'\u1F27' - | '\u1F30' ..'\u1F37' - | '\u1F40' ..'\u1F45' - | '\u1F50' ..'\u1F57' - | '\u1F60' ..'\u1F67' - | '\u1F70' ..'\u1F7D' - | '\u1F80' ..'\u1F87' - | '\u1F90' ..'\u1F97' - | '\u1FA0' ..'\u1FA7' - | '\u1FB0' ..'\u1FB4' - | '\u1FB6' - | '\u1FB7' - | '\u1FBE' - | '\u1FC2' ..'\u1FC4' - | '\u1FC6' - | '\u1FC7' - | '\u1FD0' ..'\u1FD3' - | '\u1FD6' - | '\u1FD7' - | '\u1FE0' ..'\u1FE7' - | '\u1FF2' ..'\u1FF4' - | '\u1FF6' - | '\u1FF7' - | '\u210A' - | '\u210E' - | '\u210F' - | '\u2113' - | '\u212F' - | '\u2134' - | '\u2139' - | '\u213C' - | '\u213D' - | '\u2146' ..'\u2149' - | '\u214E' - | '\u2184' - | '\u2C30' ..'\u2C5E' - | '\u2C61' - | '\u2C65' - | '\u2C66' - | '\u2C68' - | '\u2C6A' - | '\u2C6C' - | '\u2C71' - | '\u2C73' - | '\u2C74' - | '\u2C76' ..'\u2C7B' - | '\u2C81' - | '\u2C83' - | '\u2C85' - | '\u2C87' - | '\u2C89' - | '\u2C8B' - | '\u2C8D' - | '\u2C8F' - | '\u2C91' - | '\u2C93' - | '\u2C95' - | '\u2C97' - | '\u2C99' - | '\u2C9B' - | '\u2C9D' - | '\u2C9F' - | '\u2CA1' - | '\u2CA3' - | '\u2CA5' - | '\u2CA7' - | '\u2CA9' - | '\u2CAB' - | '\u2CAD' - | '\u2CAF' - | '\u2CB1' - | '\u2CB3' - | '\u2CB5' - | '\u2CB7' - | '\u2CB9' - | '\u2CBB' - | '\u2CBD' - | '\u2CBF' - | '\u2CC1' - | '\u2CC3' - | '\u2CC5' - | '\u2CC7' - | '\u2CC9' - | '\u2CCB' - | '\u2CCD' - | '\u2CCF' - | '\u2CD1' - | '\u2CD3' - | '\u2CD5' - | '\u2CD7' - | '\u2CD9' - | '\u2CDB' - | '\u2CDD' - | '\u2CDF' - | '\u2CE1' - | '\u2CE3' - | '\u2CE4' - | '\u2CEC' - | '\u2CEE' - | '\u2CF3' - | '\u2D00' ..'\u2D25' - | '\u2D27' - | '\u2D2D' - | '\uA641' - | '\uA643' - | '\uA645' - | '\uA647' - | '\uA649' - | '\uA64B' - | '\uA64D' - | '\uA64F' - | '\uA651' - | '\uA653' - | '\uA655' - | '\uA657' - | '\uA659' - | '\uA65B' - | '\uA65D' - | '\uA65F' - | '\uA661' - | '\uA663' - | '\uA665' - | '\uA667' - | '\uA669' - | '\uA66B' - | '\uA66D' - | '\uA681' - | '\uA683' - | '\uA685' - | '\uA687' - | '\uA689' - | '\uA68B' - | '\uA68D' - | '\uA68F' - | '\uA691' - | '\uA693' - | '\uA695' - | '\uA697' - | '\uA723' - | '\uA725' - | '\uA727' - | '\uA729' - | '\uA72B' - | '\uA72D' - | '\uA72F' ..'\uA731' - | '\uA733' - | '\uA735' - | '\uA737' - | '\uA739' - | '\uA73B' - | '\uA73D' - | '\uA73F' - | '\uA741' - | '\uA743' - | '\uA745' - | '\uA747' - | '\uA749' - | '\uA74B' - | '\uA74D' - | '\uA74F' - | '\uA751' - | '\uA753' - | '\uA755' - | '\uA757' - | '\uA759' - | '\uA75B' - | '\uA75D' - | '\uA75F' - | '\uA761' - | '\uA763' - | '\uA765' - | '\uA767' - | '\uA769' - | '\uA76B' - | '\uA76D' - | '\uA76F' - | '\uA771' ..'\uA778' - | '\uA77A' - | '\uA77C' - | '\uA77F' - | '\uA781' - | '\uA783' - | '\uA785' - | '\uA787' - | '\uA78C' - | '\uA78E' - | '\uA791' - | '\uA793' - | '\uA7A1' - | '\uA7A3' - | '\uA7A5' - | '\uA7A7' - | '\uA7A9' - | '\uA7FA' - | '\uFB00' ..'\uFB06' - | '\uFB13' ..'\uFB17' - | '\uFF41' ..'\uFF5A' -; - -UNICODE_CLASS_LM: - '\u02B0' ..'\u02C1' - | '\u02C6' ..'\u02D1' - | '\u02E0' ..'\u02E4' - | '\u02EC' - | '\u02EE' - | '\u0374' - | '\u037A' - | '\u0559' - | '\u0640' - | '\u06E5' - | '\u06E6' - | '\u07F4' - | '\u07F5' - | '\u07FA' - | '\u081A' - | '\u0824' - | '\u0828' - | '\u0971' - | '\u0E46' - | '\u0EC6' - | '\u10FC' - | '\u17D7' - | '\u1843' - | '\u1AA7' - | '\u1C78' ..'\u1C7D' - | '\u1D2C' ..'\u1D6A' - | '\u1D78' - | '\u1D9B' ..'\u1DBF' - | '\u2071' - | '\u207F' - | '\u2090' ..'\u209C' - | '\u2C7C' - | '\u2C7D' - | '\u2D6F' - | '\u2E2F' - | '\u3005' - | '\u3031' ..'\u3035' - | '\u303B' - | '\u309D' - | '\u309E' - | '\u30FC' ..'\u30FE' - | '\uA015' - | '\uA4F8' ..'\uA4FD' - | '\uA60C' - | '\uA67F' - | '\uA717' ..'\uA71F' - | '\uA770' - | '\uA788' - | '\uA7F8' - | '\uA7F9' - | '\uA9CF' - | '\uAA70' - | '\uAADD' - | '\uAAF3' - | '\uAAF4' - | '\uFF70' - | '\uFF9E' - | '\uFF9F' -; - -UNICODE_CLASS_LO: - '\u00AA' - | '\u00BA' - | '\u01BB' - | '\u01C0' ..'\u01C3' - | '\u0294' - | '\u05D0' ..'\u05EA' - | '\u05F0' ..'\u05F2' - | '\u0620' ..'\u063F' - | '\u0641' ..'\u064A' - | '\u066E' - | '\u066F' - | '\u0671' ..'\u06D3' - | '\u06D5' - | '\u06EE' - | '\u06EF' - | '\u06FA' ..'\u06FC' - | '\u06FF' - | '\u0710' - | '\u0712' ..'\u072F' - | '\u074D' ..'\u07A5' - | '\u07B1' - | '\u07CA' ..'\u07EA' - | '\u0800' ..'\u0815' - | '\u0840' ..'\u0858' - | '\u08A0' - | '\u08A2' ..'\u08AC' - | '\u0904' ..'\u0939' - | '\u093D' - | '\u0950' - | '\u0958' ..'\u0961' - | '\u0972' ..'\u0977' - | '\u0979' ..'\u097F' - | '\u0985' ..'\u098C' - | '\u098F' - | '\u0990' - | '\u0993' ..'\u09A8' - | '\u09AA' ..'\u09B0' - | '\u09B2' - | '\u09B6' ..'\u09B9' - | '\u09BD' - | '\u09CE' - | '\u09DC' - | '\u09DD' - | '\u09DF' ..'\u09E1' - | '\u09F0' - | '\u09F1' - | '\u0A05' ..'\u0A0A' - | '\u0A0F' - | '\u0A10' - | '\u0A13' ..'\u0A28' - | '\u0A2A' ..'\u0A30' - | '\u0A32' - | '\u0A33' - | '\u0A35' - | '\u0A36' - | '\u0A38' - | '\u0A39' - | '\u0A59' ..'\u0A5C' - | '\u0A5E' - | '\u0A72' ..'\u0A74' - | '\u0A85' ..'\u0A8D' - | '\u0A8F' ..'\u0A91' - | '\u0A93' ..'\u0AA8' - | '\u0AAA' ..'\u0AB0' - | '\u0AB2' - | '\u0AB3' - | '\u0AB5' ..'\u0AB9' - | '\u0ABD' - | '\u0AD0' - | '\u0AE0' - | '\u0AE1' - | '\u0B05' ..'\u0B0C' - | '\u0B0F' - | '\u0B10' - | '\u0B13' ..'\u0B28' - | '\u0B2A' ..'\u0B30' - | '\u0B32' - | '\u0B33' - | '\u0B35' ..'\u0B39' - | '\u0B3D' - | '\u0B5C' - | '\u0B5D' - | '\u0B5F' ..'\u0B61' - | '\u0B71' - | '\u0B83' - | '\u0B85' ..'\u0B8A' - | '\u0B8E' ..'\u0B90' - | '\u0B92' ..'\u0B95' - | '\u0B99' - | '\u0B9A' - | '\u0B9C' - | '\u0B9E' - | '\u0B9F' - | '\u0BA3' - | '\u0BA4' - | '\u0BA8' ..'\u0BAA' - | '\u0BAE' ..'\u0BB9' - | '\u0BD0' - | '\u0C05' ..'\u0C0C' - | '\u0C0E' ..'\u0C10' - | '\u0C12' ..'\u0C28' - | '\u0C2A' ..'\u0C33' - | '\u0C35' ..'\u0C39' - | '\u0C3D' - | '\u0C58' - | '\u0C59' - | '\u0C60' - | '\u0C61' - | '\u0C85' ..'\u0C8C' - | '\u0C8E' ..'\u0C90' - | '\u0C92' ..'\u0CA8' - | '\u0CAA' ..'\u0CB3' - | '\u0CB5' ..'\u0CB9' - | '\u0CBD' - | '\u0CDE' - | '\u0CE0' - | '\u0CE1' - | '\u0CF1' - | '\u0CF2' - | '\u0D05' ..'\u0D0C' - | '\u0D0E' ..'\u0D10' - | '\u0D12' ..'\u0D3A' - | '\u0D3D' - | '\u0D4E' - | '\u0D60' - | '\u0D61' - | '\u0D7A' ..'\u0D7F' - | '\u0D85' ..'\u0D96' - | '\u0D9A' ..'\u0DB1' - | '\u0DB3' ..'\u0DBB' - | '\u0DBD' - | '\u0DC0' ..'\u0DC6' - | '\u0E01' ..'\u0E30' - | '\u0E32' - | '\u0E33' - | '\u0E40' ..'\u0E45' - | '\u0E81' - | '\u0E82' - | '\u0E84' - | '\u0E87' - | '\u0E88' - | '\u0E8A' - | '\u0E8D' - | '\u0E94' ..'\u0E97' - | '\u0E99' ..'\u0E9F' - | '\u0EA1' ..'\u0EA3' - | '\u0EA5' - | '\u0EA7' - | '\u0EAA' - | '\u0EAB' - | '\u0EAD' ..'\u0EB0' - | '\u0EB2' - | '\u0EB3' - | '\u0EBD' - | '\u0EC0' ..'\u0EC4' - | '\u0EDC' ..'\u0EDF' - | '\u0F00' - | '\u0F40' ..'\u0F47' - | '\u0F49' ..'\u0F6C' - | '\u0F88' ..'\u0F8C' - | '\u1000' ..'\u102A' - | '\u103F' - | '\u1050' ..'\u1055' - | '\u105A' ..'\u105D' - | '\u1061' - | '\u1065' - | '\u1066' - | '\u106E' ..'\u1070' - | '\u1075' ..'\u1081' - | '\u108E' - | '\u10D0' ..'\u10FA' - | '\u10FD' ..'\u1248' - | '\u124A' ..'\u124D' - | '\u1250' ..'\u1256' - | '\u1258' - | '\u125A' ..'\u125D' - | '\u1260' ..'\u1288' - | '\u128A' ..'\u128D' - | '\u1290' ..'\u12B0' - | '\u12B2' ..'\u12B5' - | '\u12B8' ..'\u12BE' - | '\u12C0' - | '\u12C2' ..'\u12C5' - | '\u12C8' ..'\u12D6' - | '\u12D8' ..'\u1310' - | '\u1312' ..'\u1315' - | '\u1318' ..'\u135A' - | '\u1380' ..'\u138F' - | '\u13A0' ..'\u13F4' - | '\u1401' ..'\u166C' - | '\u166F' ..'\u167F' - | '\u1681' ..'\u169A' - | '\u16A0' ..'\u16EA' - | '\u1700' ..'\u170C' - | '\u170E' ..'\u1711' - | '\u1720' ..'\u1731' - | '\u1740' ..'\u1751' - | '\u1760' ..'\u176C' - | '\u176E' ..'\u1770' - | '\u1780' ..'\u17B3' - | '\u17DC' - | '\u1820' ..'\u1842' - | '\u1844' ..'\u1877' - | '\u1880' ..'\u18A8' - | '\u18AA' - | '\u18B0' ..'\u18F5' - | '\u1900' ..'\u191C' - | '\u1950' ..'\u196D' - | '\u1970' ..'\u1974' - | '\u1980' ..'\u19AB' - | '\u19C1' ..'\u19C7' - | '\u1A00' ..'\u1A16' - | '\u1A20' ..'\u1A54' - | '\u1B05' ..'\u1B33' - | '\u1B45' ..'\u1B4B' - | '\u1B83' ..'\u1BA0' - | '\u1BAE' - | '\u1BAF' - | '\u1BBA' ..'\u1BE5' - | '\u1C00' ..'\u1C23' - | '\u1C4D' ..'\u1C4F' - | '\u1C5A' ..'\u1C77' - | '\u1CE9' ..'\u1CEC' - | '\u1CEE' ..'\u1CF1' - | '\u1CF5' - | '\u1CF6' - | '\u2135' ..'\u2138' - | '\u2D30' ..'\u2D67' - | '\u2D80' ..'\u2D96' - | '\u2DA0' ..'\u2DA6' - | '\u2DA8' ..'\u2DAE' - | '\u2DB0' ..'\u2DB6' - | '\u2DB8' ..'\u2DBE' - | '\u2DC0' ..'\u2DC6' - | '\u2DC8' ..'\u2DCE' - | '\u2DD0' ..'\u2DD6' - | '\u2DD8' ..'\u2DDE' - | '\u3006' - | '\u303C' - | '\u3041' ..'\u3096' - | '\u309F' - | '\u30A1' ..'\u30FA' - | '\u30FF' - | '\u3105' ..'\u312D' - | '\u3131' ..'\u318E' - | '\u31A0' ..'\u31BA' - | '\u31F0' ..'\u31FF' - | '\u3400' ..'\u4DB5' - | '\u4E00' ..'\u9FCC' - | '\uA000' ..'\uA014' - | '\uA016' ..'\uA48C' - | '\uA4D0' ..'\uA4F7' - | '\uA500' ..'\uA60B' - | '\uA610' ..'\uA61F' - | '\uA62A' - | '\uA62B' - | '\uA66E' - | '\uA6A0' ..'\uA6E5' - | '\uA7FB' ..'\uA801' - | '\uA803' ..'\uA805' - | '\uA807' ..'\uA80A' - | '\uA80C' ..'\uA822' - | '\uA840' ..'\uA873' - | '\uA882' ..'\uA8B3' - | '\uA8F2' ..'\uA8F7' - | '\uA8FB' - | '\uA90A' ..'\uA925' - | '\uA930' ..'\uA946' - | '\uA960' ..'\uA97C' - | '\uA984' ..'\uA9B2' - | '\uAA00' ..'\uAA28' - | '\uAA40' ..'\uAA42' - | '\uAA44' ..'\uAA4B' - | '\uAA60' ..'\uAA6F' - | '\uAA71' ..'\uAA76' - | '\uAA7A' - | '\uAA80' ..'\uAAAF' - | '\uAAB1' - | '\uAAB5' - | '\uAAB6' - | '\uAAB9' ..'\uAABD' - | '\uAAC0' - | '\uAAC2' - | '\uAADB' - | '\uAADC' - | '\uAAE0' ..'\uAAEA' - | '\uAAF2' - | '\uAB01' ..'\uAB06' - | '\uAB09' ..'\uAB0E' - | '\uAB11' ..'\uAB16' - | '\uAB20' ..'\uAB26' - | '\uAB28' ..'\uAB2E' - | '\uABC0' ..'\uABE2' - | '\uAC00' - | '\uD7A3' - | '\uD7B0' ..'\uD7C6' - | '\uD7CB' ..'\uD7FB' - | '\uF900' ..'\uFA6D' - | '\uFA70' ..'\uFAD9' - | '\uFB1D' - | '\uFB1F' ..'\uFB28' - | '\uFB2A' ..'\uFB36' - | '\uFB38' ..'\uFB3C' - | '\uFB3E' - | '\uFB40' - | '\uFB41' - | '\uFB43' - | '\uFB44' - | '\uFB46' ..'\uFBB1' - | '\uFBD3' ..'\uFD3D' - | '\uFD50' ..'\uFD8F' - | '\uFD92' ..'\uFDC7' - | '\uFDF0' ..'\uFDFB' - | '\uFE70' ..'\uFE74' - | '\uFE76' ..'\uFEFC' - | '\uFF66' ..'\uFF6F' - | '\uFF71' ..'\uFF9D' - | '\uFFA0' ..'\uFFBE' - | '\uFFC2' ..'\uFFC7' - | '\uFFCA' ..'\uFFCF' - | '\uFFD2' ..'\uFFD7' - | '\uFFDA' ..'\uFFDC' -; - -UNICODE_CLASS_LT: - '\u01C5' - | '\u01C8' - | '\u01CB' - | '\u01F2' - | '\u1F88' ..'\u1F8F' - | '\u1F98' ..'\u1F9F' - | '\u1FA8' ..'\u1FAF' - | '\u1FBC' - | '\u1FCC' - | '\u1FFC' -; - -UNICODE_CLASS_LU: - '\u0041' ..'\u005A' - | '\u00C0' ..'\u00D6' - | '\u00D8' ..'\u00DE' - | '\u0100' - | '\u0102' - | '\u0104' - | '\u0106' - | '\u0108' - | '\u010A' - | '\u010C' - | '\u010E' - | '\u0110' - | '\u0112' - | '\u0114' - | '\u0116' - | '\u0118' - | '\u011A' - | '\u011C' - | '\u011E' - | '\u0120' - | '\u0122' - | '\u0124' - | '\u0126' - | '\u0128' - | '\u012A' - | '\u012C' - | '\u012E' - | '\u0130' - | '\u0132' - | '\u0134' - | '\u0136' - | '\u0139' - | '\u013B' - | '\u013D' - | '\u013F' - | '\u0141' - | '\u0143' - | '\u0145' - | '\u0147' - | '\u014A' - | '\u014C' - | '\u014E' - | '\u0150' - | '\u0152' - | '\u0154' - | '\u0156' - | '\u0158' - | '\u015A' - | '\u015C' - | '\u015E' - | '\u0160' - | '\u0162' - | '\u0164' - | '\u0166' - | '\u0168' - | '\u016A' - | '\u016C' - | '\u016E' - | '\u0170' - | '\u0172' - | '\u0174' - | '\u0176' - | '\u0178' - | '\u0179' - | '\u017B' - | '\u017D' - | '\u0181' - | '\u0182' - | '\u0184' - | '\u0186' - | '\u0187' - | '\u0189' ..'\u018B' - | '\u018E' ..'\u0191' - | '\u0193' - | '\u0194' - | '\u0196' ..'\u0198' - | '\u019C' - | '\u019D' - | '\u019F' - | '\u01A0' - | '\u01A2' - | '\u01A4' - | '\u01A6' - | '\u01A7' - | '\u01A9' - | '\u01AC' - | '\u01AE' - | '\u01AF' - | '\u01B1' ..'\u01B3' - | '\u01B5' - | '\u01B7' - | '\u01B8' - | '\u01BC' - | '\u01C4' - | '\u01C7' - | '\u01CA' - | '\u01CD' - | '\u01CF' - | '\u01D1' - | '\u01D3' - | '\u01D5' - | '\u01D7' - | '\u01D9' - | '\u01DB' - | '\u01DE' - | '\u01E0' - | '\u01E2' - | '\u01E4' - | '\u01E6' - | '\u01E8' - | '\u01EA' - | '\u01EC' - | '\u01EE' - | '\u01F1' - | '\u01F4' - | '\u01F6' ..'\u01F8' - | '\u01FA' - | '\u01FC' - | '\u01FE' - | '\u0200' - | '\u0202' - | '\u0204' - | '\u0206' - | '\u0208' - | '\u020A' - | '\u020C' - | '\u020E' - | '\u0210' - | '\u0212' - | '\u0214' - | '\u0216' - | '\u0218' - | '\u021A' - | '\u021C' - | '\u021E' - | '\u0220' - | '\u0222' - | '\u0224' - | '\u0226' - | '\u0228' - | '\u022A' - | '\u022C' - | '\u022E' - | '\u0230' - | '\u0232' - | '\u023A' - | '\u023B' - | '\u023D' - | '\u023E' - | '\u0241' - | '\u0243' ..'\u0246' - | '\u0248' - | '\u024A' - | '\u024C' - | '\u024E' - | '\u0370' - | '\u0372' - | '\u0376' - | '\u0386' - | '\u0388' ..'\u038A' - | '\u038C' - | '\u038E' - | '\u038F' - | '\u0391' ..'\u03A1' - | '\u03A3' ..'\u03AB' - | '\u03CF' - | '\u03D2' ..'\u03D4' - | '\u03D8' - | '\u03DA' - | '\u03DC' - | '\u03DE' - | '\u03E0' - | '\u03E2' - | '\u03E4' - | '\u03E6' - | '\u03E8' - | '\u03EA' - | '\u03EC' - | '\u03EE' - | '\u03F4' - | '\u03F7' - | '\u03F9' - | '\u03FA' - | '\u03FD' ..'\u042F' - | '\u0460' - | '\u0462' - | '\u0464' - | '\u0466' - | '\u0468' - | '\u046A' - | '\u046C' - | '\u046E' - | '\u0470' - | '\u0472' - | '\u0474' - | '\u0476' - | '\u0478' - | '\u047A' - | '\u047C' - | '\u047E' - | '\u0480' - | '\u048A' - | '\u048C' - | '\u048E' - | '\u0490' - | '\u0492' - | '\u0494' - | '\u0496' - | '\u0498' - | '\u049A' - | '\u049C' - | '\u049E' - | '\u04A0' - | '\u04A2' - | '\u04A4' - | '\u04A6' - | '\u04A8' - | '\u04AA' - | '\u04AC' - | '\u04AE' - | '\u04B0' - | '\u04B2' - | '\u04B4' - | '\u04B6' - | '\u04B8' - | '\u04BA' - | '\u04BC' - | '\u04BE' - | '\u04C0' - | '\u04C1' - | '\u04C3' - | '\u04C5' - | '\u04C7' - | '\u04C9' - | '\u04CB' - | '\u04CD' - | '\u04D0' - | '\u04D2' - | '\u04D4' - | '\u04D6' - | '\u04D8' - | '\u04DA' - | '\u04DC' - | '\u04DE' - | '\u04E0' - | '\u04E2' - | '\u04E4' - | '\u04E6' - | '\u04E8' - | '\u04EA' - | '\u04EC' - | '\u04EE' - | '\u04F0' - | '\u04F2' - | '\u04F4' - | '\u04F6' - | '\u04F8' - | '\u04FA' - | '\u04FC' - | '\u04FE' - | '\u0500' - | '\u0502' - | '\u0504' - | '\u0506' - | '\u0508' - | '\u050A' - | '\u050C' - | '\u050E' - | '\u0510' - | '\u0512' - | '\u0514' - | '\u0516' - | '\u0518' - | '\u051A' - | '\u051C' - | '\u051E' - | '\u0520' - | '\u0522' - | '\u0524' - | '\u0526' - | '\u0531' ..'\u0556' - | '\u10A0' ..'\u10C5' - | '\u10C7' - | '\u10CD' - | '\u1E00' - | '\u1E02' - | '\u1E04' - | '\u1E06' - | '\u1E08' - | '\u1E0A' - | '\u1E0C' - | '\u1E0E' - | '\u1E10' - | '\u1E12' - | '\u1E14' - | '\u1E16' - | '\u1E18' - | '\u1E1A' - | '\u1E1C' - | '\u1E1E' - | '\u1E20' - | '\u1E22' - | '\u1E24' - | '\u1E26' - | '\u1E28' - | '\u1E2A' - | '\u1E2C' - | '\u1E2E' - | '\u1E30' - | '\u1E32' - | '\u1E34' - | '\u1E36' - | '\u1E38' - | '\u1E3A' - | '\u1E3C' - | '\u1E3E' - | '\u1E40' - | '\u1E42' - | '\u1E44' - | '\u1E46' - | '\u1E48' - | '\u1E4A' - | '\u1E4C' - | '\u1E4E' - | '\u1E50' - | '\u1E52' - | '\u1E54' - | '\u1E56' - | '\u1E58' - | '\u1E5A' - | '\u1E5C' - | '\u1E5E' - | '\u1E60' - | '\u1E62' - | '\u1E64' - | '\u1E66' - | '\u1E68' - | '\u1E6A' - | '\u1E6C' - | '\u1E6E' - | '\u1E70' - | '\u1E72' - | '\u1E74' - | '\u1E76' - | '\u1E78' - | '\u1E7A' - | '\u1E7C' - | '\u1E7E' - | '\u1E80' - | '\u1E82' - | '\u1E84' - | '\u1E86' - | '\u1E88' - | '\u1E8A' - | '\u1E8C' - | '\u1E8E' - | '\u1E90' - | '\u1E92' - | '\u1E94' - | '\u1E9E' - | '\u1EA0' - | '\u1EA2' - | '\u1EA4' - | '\u1EA6' - | '\u1EA8' - | '\u1EAA' - | '\u1EAC' - | '\u1EAE' - | '\u1EB0' - | '\u1EB2' - | '\u1EB4' - | '\u1EB6' - | '\u1EB8' - | '\u1EBA' - | '\u1EBC' - | '\u1EBE' - | '\u1EC0' - | '\u1EC2' - | '\u1EC4' - | '\u1EC6' - | '\u1EC8' - | '\u1ECA' - | '\u1ECC' - | '\u1ECE' - | '\u1ED0' - | '\u1ED2' - | '\u1ED4' - | '\u1ED6' - | '\u1ED8' - | '\u1EDA' - | '\u1EDC' - | '\u1EDE' - | '\u1EE0' - | '\u1EE2' - | '\u1EE4' - | '\u1EE6' - | '\u1EE8' - | '\u1EEA' - | '\u1EEC' - | '\u1EEE' - | '\u1EF0' - | '\u1EF2' - | '\u1EF4' - | '\u1EF6' - | '\u1EF8' - | '\u1EFA' - | '\u1EFC' - | '\u1EFE' - | '\u1F08' ..'\u1F0F' - | '\u1F18' ..'\u1F1D' - | '\u1F28' ..'\u1F2F' - | '\u1F38' ..'\u1F3F' - | '\u1F48' ..'\u1F4D' - | '\u1F59' - | '\u1F5B' - | '\u1F5D' - | '\u1F5F' - | '\u1F68' ..'\u1F6F' - | '\u1FB8' ..'\u1FBB' - | '\u1FC8' ..'\u1FCB' - | '\u1FD8' ..'\u1FDB' - | '\u1FE8' ..'\u1FEC' - | '\u1FF8' ..'\u1FFB' - | '\u2102' - | '\u2107' - | '\u210B' ..'\u210D' - | '\u2110' ..'\u2112' - | '\u2115' - | '\u2119' ..'\u211D' - | '\u2124' - | '\u2126' - | '\u2128' - | '\u212A' ..'\u212D' - | '\u2130' ..'\u2133' - | '\u213E' - | '\u213F' - | '\u2145' - | '\u2183' - | '\u2C00' ..'\u2C2E' - | '\u2C60' - | '\u2C62' ..'\u2C64' - | '\u2C67' - | '\u2C69' - | '\u2C6B' - | '\u2C6D' ..'\u2C70' - | '\u2C72' - | '\u2C75' - | '\u2C7E' ..'\u2C80' - | '\u2C82' - | '\u2C84' - | '\u2C86' - | '\u2C88' - | '\u2C8A' - | '\u2C8C' - | '\u2C8E' - | '\u2C90' - | '\u2C92' - | '\u2C94' - | '\u2C96' - | '\u2C98' - | '\u2C9A' - | '\u2C9C' - | '\u2C9E' - | '\u2CA0' - | '\u2CA2' - | '\u2CA4' - | '\u2CA6' - | '\u2CA8' - | '\u2CAA' - | '\u2CAC' - | '\u2CAE' - | '\u2CB0' - | '\u2CB2' - | '\u2CB4' - | '\u2CB6' - | '\u2CB8' - | '\u2CBA' - | '\u2CBC' - | '\u2CBE' - | '\u2CC0' - | '\u2CC2' - | '\u2CC4' - | '\u2CC6' - | '\u2CC8' - | '\u2CCA' - | '\u2CCC' - | '\u2CCE' - | '\u2CD0' - | '\u2CD2' - | '\u2CD4' - | '\u2CD6' - | '\u2CD8' - | '\u2CDA' - | '\u2CDC' - | '\u2CDE' - | '\u2CE0' - | '\u2CE2' - | '\u2CEB' - | '\u2CED' - | '\u2CF2' - | '\uA640' - | '\uA642' - | '\uA644' - | '\uA646' - | '\uA648' - | '\uA64A' - | '\uA64C' - | '\uA64E' - | '\uA650' - | '\uA652' - | '\uA654' - | '\uA656' - | '\uA658' - | '\uA65A' - | '\uA65C' - | '\uA65E' - | '\uA660' - | '\uA662' - | '\uA664' - | '\uA666' - | '\uA668' - | '\uA66A' - | '\uA66C' - | '\uA680' - | '\uA682' - | '\uA684' - | '\uA686' - | '\uA688' - | '\uA68A' - | '\uA68C' - | '\uA68E' - | '\uA690' - | '\uA692' - | '\uA694' - | '\uA696' - | '\uA722' - | '\uA724' - | '\uA726' - | '\uA728' - | '\uA72A' - | '\uA72C' - | '\uA72E' - | '\uA732' - | '\uA734' - | '\uA736' - | '\uA738' - | '\uA73A' - | '\uA73C' - | '\uA73E' - | '\uA740' - | '\uA742' - | '\uA744' - | '\uA746' - | '\uA748' - | '\uA74A' - | '\uA74C' - | '\uA74E' - | '\uA750' - | '\uA752' - | '\uA754' - | '\uA756' - | '\uA758' - | '\uA75A' - | '\uA75C' - | '\uA75E' - | '\uA760' - | '\uA762' - | '\uA764' - | '\uA766' - | '\uA768' - | '\uA76A' - | '\uA76C' - | '\uA76E' - | '\uA779' - | '\uA77B' - | '\uA77D' - | '\uA77E' - | '\uA780' - | '\uA782' - | '\uA784' - | '\uA786' - | '\uA78B' - | '\uA78D' - | '\uA790' - | '\uA792' - | '\uA7A0' - | '\uA7A2' - | '\uA7A4' - | '\uA7A6' - | '\uA7A8' - | '\uA7AA' - | '\uFF21' ..'\uFF3A' -; - -UNICODE_CLASS_ND: - '\u0030' ..'\u0039' - | '\u0660' ..'\u0669' - | '\u06F0' ..'\u06F9' - | '\u07C0' ..'\u07C9' - | '\u0966' ..'\u096F' - | '\u09E6' ..'\u09EF' - | '\u0A66' ..'\u0A6F' - | '\u0AE6' ..'\u0AEF' - | '\u0B66' ..'\u0B6F' - | '\u0BE6' ..'\u0BEF' - | '\u0C66' ..'\u0C6F' - | '\u0CE6' ..'\u0CEF' - | '\u0D66' ..'\u0D6F' - | '\u0E50' ..'\u0E59' - | '\u0ED0' ..'\u0ED9' - | '\u0F20' ..'\u0F29' - | '\u1040' ..'\u1049' - | '\u1090' ..'\u1099' - | '\u17E0' ..'\u17E9' - | '\u1810' ..'\u1819' - | '\u1946' ..'\u194F' - | '\u19D0' ..'\u19D9' - | '\u1A80' ..'\u1A89' - | '\u1A90' ..'\u1A99' - | '\u1B50' ..'\u1B59' - | '\u1BB0' ..'\u1BB9' - | '\u1C40' ..'\u1C49' - | '\u1C50' ..'\u1C59' - | '\uA620' ..'\uA629' - | '\uA8D0' ..'\uA8D9' - | '\uA900' ..'\uA909' - | '\uA9D0' ..'\uA9D9' - | '\uAA50' ..'\uAA59' - | '\uABF0' ..'\uABF9' - | '\uFF10' ..'\uFF19' -; - -UNICODE_CLASS_NL: - '\u16EE' ..'\u16F0' - | '\u2160' ..'\u2182' - | '\u2185' ..'\u2188' - | '\u3007' - | '\u3021' ..'\u3029' - | '\u3038' ..'\u303A' - | '\uA6E6' ..'\uA6EF' -; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Lexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Lexer.g4 deleted file mode 100644 index 1c646393..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Lexer.g4 +++ /dev/null @@ -1,398 +0,0 @@ -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar CPP14Lexer; - -IntegerLiteral: - DecimalLiteral Integersuffix? - | OctalLiteral Integersuffix? - | HexadecimalLiteral Integersuffix? - | BinaryLiteral Integersuffix? -; - -CharacterLiteral: ('u' | 'U' | 'L')? '\'' Cchar+ '\''; - -FloatingLiteral: - Fractionalconstant Exponentpart? Floatingsuffix? - | Digitsequence Exponentpart Floatingsuffix? -; - -StringLiteral: Encodingprefix? (Rawstring | '"' Schar* '"'); - -BooleanLiteral: False_ | True_; - -PointerLiteral: Nullptr; - -UserDefinedLiteral: - UserDefinedIntegerLiteral - | UserDefinedFloatingLiteral - | UserDefinedStringLiteral - | UserDefinedCharacterLiteral -; - -MultiLineMacro: '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN); - -Directive: '#' ~ [\n]* -> channel (HIDDEN); -/*Keywords*/ - -Alignas: 'alignas'; - -Alignof: 'alignof'; - -Asm: 'asm'; - -Auto: 'auto'; - -Bool: 'bool'; - -Break: 'break'; - -Case: 'case'; - -Catch: 'catch'; - -Char: 'char'; - -Char16: 'char16_t'; - -Char32: 'char32_t'; - -Class: 'class'; - -Const: 'const'; - -Constexpr: 'constexpr'; - -Const_cast: 'const_cast'; - -Continue: 'continue'; - -Decltype: 'decltype'; - -Default: 'default'; - -Delete: 'delete'; - -Do: 'do'; - -Double: 'double'; - -Dynamic_cast: 'dynamic_cast'; - -Else: 'else'; - -Enum: 'enum'; - -Explicit: 'explicit'; - -Export: 'export'; - -Extern: 'extern'; - -//DO NOT RENAME - PYTHON NEEDS True and False -False_: 'false'; - -Final: 'final'; - -Float: 'float'; - -For: 'for'; - -Friend: 'friend'; - -Goto: 'goto'; - -If: 'if'; - -Inline: 'inline'; - -Int: 'int'; - -Long: 'long'; - -Mutable: 'mutable'; - -Namespace: 'namespace'; - -New: 'new'; - -Noexcept: 'noexcept'; - -Nullptr: 'nullptr'; - -Operator: 'operator'; - -Override: 'override'; - -Private: 'private'; - -Protected: 'protected'; - -Public: 'public'; - -Register: 'register'; - -Reinterpret_cast: 'reinterpret_cast'; - -Return: 'return'; - -Short: 'short'; - -Signed: 'signed'; - -Sizeof: 'sizeof'; - -Static: 'static'; - -Static_assert: 'static_assert'; - -Static_cast: 'static_cast'; - -Struct: 'struct'; - -Switch: 'switch'; - -Template: 'template'; - -This: 'this'; - -Thread_local: 'thread_local'; - -Throw: 'throw'; - -//DO NOT RENAME - PYTHON NEEDS True and False -True_: 'true'; - -Try: 'try'; - -Typedef: 'typedef'; - -Typeid_: 'typeid'; - -Typename_: 'typename'; - -Union: 'union'; - -Unsigned: 'unsigned'; - -Using: 'using'; - -Virtual: 'virtual'; - -Void: 'void'; - -Volatile: 'volatile'; - -Wchar: 'wchar_t'; - -While: 'while'; -/*Operators*/ - -LeftParen: '('; - -RightParen: ')'; - -LeftBracket: '['; - -RightBracket: ']'; - -LeftBrace: '{'; - -RightBrace: '}'; - -Plus: '+'; - -Minus: '-'; - -Star: '*'; - -Div: '/'; - -Mod: '%'; - -Caret: '^'; - -And: '&'; - -Or: '|'; - -Tilde: '~'; - -Not: '!' | 'not'; - -Assign: '='; - -Less: '<'; - -Greater: '>'; - -PlusAssign: '+='; - -MinusAssign: '-='; - -StarAssign: '*='; - -DivAssign: '/='; - -ModAssign: '%='; - -XorAssign: '^='; - -AndAssign: '&='; - -OrAssign: '|='; - -LeftShiftAssign: '<<='; - -RightShiftAssign: '>>='; - -Equal: '=='; - -NotEqual: '!='; - -LessEqual: '<='; - -GreaterEqual: '>='; - -AndAnd: '&&' | 'and'; - -OrOr: '||' | 'or'; - -PlusPlus: '++'; - -MinusMinus: '--'; - -Comma: ','; - -ArrowStar: '->*'; - -Arrow: '->'; - -Question: '?'; - -Colon: ':'; - -Doublecolon: '::'; - -Semi: ';'; - -Dot: '.'; - -DotStar: '.*'; - -Ellipsis: '...'; - -fragment Hexquad: HEXADECIMALDIGIT HEXADECIMALDIGIT HEXADECIMALDIGIT HEXADECIMALDIGIT; - -fragment Universalcharactername: '\\u' Hexquad | '\\U' Hexquad Hexquad; - -Identifier: - /* - Identifiernondigit | Identifier Identifiernondigit | Identifier DIGIT - */ Identifiernondigit (Identifiernondigit | DIGIT)* -; - -fragment Identifiernondigit: NONDIGIT | Universalcharactername; - -fragment NONDIGIT: [a-zA-Z_]; - -fragment DIGIT: [0-9]; - -DecimalLiteral: NONZERODIGIT ('\''? DIGIT)*; - -OctalLiteral: '0' ('\''? OCTALDIGIT)*; - -HexadecimalLiteral: ('0x' | '0X') HEXADECIMALDIGIT ( '\''? HEXADECIMALDIGIT)*; - -BinaryLiteral: ('0b' | '0B') BINARYDIGIT ('\''? BINARYDIGIT)*; - -fragment NONZERODIGIT: [1-9]; - -fragment OCTALDIGIT: [0-7]; - -fragment HEXADECIMALDIGIT: [0-9a-fA-F]; - -fragment BINARYDIGIT: [01]; - -Integersuffix: - Unsignedsuffix Longsuffix? - | Unsignedsuffix Longlongsuffix? - | Longsuffix Unsignedsuffix? - | Longlongsuffix Unsignedsuffix? -; - -fragment Unsignedsuffix: [uU]; - -fragment Longsuffix: [lL]; - -fragment Longlongsuffix: 'll' | 'LL'; - -fragment Cchar: ~ ['\\\r\n] | Escapesequence | Universalcharactername; - -fragment Escapesequence: Simpleescapesequence | Octalescapesequence | Hexadecimalescapesequence; - -fragment Simpleescapesequence: - '\\\'' - | '\\"' - | '\\?' - | '\\\\' - | '\\a' - | '\\b' - | '\\f' - | '\\n' - | '\\r' - | '\\' ('\r' '\n'? | '\n') - | '\\t' - | '\\v' -; - -fragment Octalescapesequence: - '\\' OCTALDIGIT - | '\\' OCTALDIGIT OCTALDIGIT - | '\\' OCTALDIGIT OCTALDIGIT OCTALDIGIT -; - -fragment Hexadecimalescapesequence: '\\x' HEXADECIMALDIGIT+; - -fragment Fractionalconstant: Digitsequence? '.' Digitsequence | Digitsequence '.'; - -fragment Exponentpart: 'e' SIGN? Digitsequence | 'E' SIGN? Digitsequence; - -fragment SIGN: [+-]; - -fragment Digitsequence: DIGIT ('\''? DIGIT)*; - -fragment Floatingsuffix: [flFL]; - -fragment Encodingprefix: 'u8' | 'u' | 'U' | 'L'; - -fragment Schar: ~ ["\\\r\n] | Escapesequence | Universalcharactername; - -fragment Rawstring: 'R"' ( '\\' ["()] | ~[\r\n (])*? '(' ~[)]*? ')' ( '\\' ["()] | ~[\r\n "])*? '"'; - -UserDefinedIntegerLiteral: - DecimalLiteral Udsuffix - | OctalLiteral Udsuffix - | HexadecimalLiteral Udsuffix - | BinaryLiteral Udsuffix -; - -UserDefinedFloatingLiteral: - Fractionalconstant Exponentpart? Udsuffix - | Digitsequence Exponentpart Udsuffix -; - -UserDefinedStringLiteral: StringLiteral Udsuffix; - -UserDefinedCharacterLiteral: CharacterLiteral Udsuffix; - -fragment Udsuffix: Identifier; - -Whitespace: [ \t]+ -> skip; - -Newline: ('\r' '\n'? | '\n') -> skip; - -BlockComment: '/*' .*? '*/' -> skip; - -LineComment: '//' ~ [\r\n]* -> skip; diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Parser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Parser.g4 deleted file mode 100644 index c21e1837..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/cpp/CPP14Parser.g4 +++ /dev/null @@ -1,1076 +0,0 @@ -/******************************************************************************* - * The MIT License (MIT) - * - * Copyright (c) 2015 Camilo Sanchez (Camiloasc1) 2020 Martin Mirchev (Marti2203) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * **************************************************************************** - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar CPP14Parser; - -options { - superClass = CPP14ParserBase; - tokenVocab = CPP14Lexer; -} - -// Insert here @header for C++ parser. - -/*Basic concepts*/ - -translationUnit - : declarationSeq? EOF - ; - -/*Expressions*/ - -primaryExpression - : literal+ - | This - | LeftParen expression RightParen - | idExpression - | lambdaExpression - ; - -idExpression - : unqualifiedId - | qualifiedId - ; - -unqualifiedId - : Identifier - | operatorFunctionId - | conversionFunctionId - | literalOperatorId - | Tilde (className | decltypeSpecifier) - | templateId - ; - -qualifiedId - : nestedNameSpecifier Template? unqualifiedId - ; - -nestedNameSpecifier - : (theTypeName | namespaceName | decltypeSpecifier)? Doublecolon - | nestedNameSpecifier ( Identifier | Template? simpleTemplateId) Doublecolon - ; - -lambdaExpression - : lambdaIntroducer lambdaDeclarator? compoundStatement - ; - -lambdaIntroducer - : LeftBracket lambdaCapture? RightBracket - ; - -lambdaCapture - : captureList - | captureDefault (Comma captureList)? - ; - -captureDefault - : And - | Assign - ; - -captureList - : capture (Comma capture)* Ellipsis? - ; - -capture - : simpleCapture - | initCapture - ; - -simpleCapture - : And? Identifier - | This - ; - -initCapture - : And? Identifier initializer - ; - -lambdaDeclarator - : LeftParen parameterDeclarationClause? RightParen Mutable? exceptionSpecification? attributeSpecifierSeq? trailingReturnType? - ; - -postfixExpression - : primaryExpression - | postfixExpression LeftBracket (expression | bracedInitList) RightBracket - | postfixExpression LeftParen expressionList? RightParen - | (simpleTypeSpecifier | typeNameSpecifier) ( - LeftParen expressionList? RightParen - | bracedInitList - ) - | postfixExpression (Dot | Arrow) (Template? idExpression | pseudoDestructorName) - | postfixExpression (PlusPlus | MinusMinus) - | (Dynamic_cast | Static_cast | Reinterpret_cast | Const_cast) Less theTypeId Greater LeftParen expression RightParen - | typeIdOfTheTypeId LeftParen (expression | theTypeId) RightParen - ; - -/* - add a middle layer to eliminate duplicated function declarations - */ - -typeIdOfTheTypeId - : Typeid_ - ; - -expressionList - : initializerList - ; - -pseudoDestructorName - : nestedNameSpecifier? (theTypeName Doublecolon)? Tilde theTypeName - | nestedNameSpecifier Template simpleTemplateId Doublecolon Tilde theTypeName - | Tilde decltypeSpecifier - ; - -unaryExpression - : postfixExpression - | (PlusPlus | MinusMinus | unaryOperator | Sizeof) unaryExpression - | Sizeof (LeftParen theTypeId RightParen | Ellipsis LeftParen Identifier RightParen) - | Alignof LeftParen theTypeId RightParen - | noExceptExpression - | newExpression_ - | deleteExpression - ; - -unaryOperator - : Or - | Star - | And - | Plus - | Tilde - | Minus - | Not - ; - -newExpression_ - : Doublecolon? New newPlacement? (newTypeId | LeftParen theTypeId RightParen) newInitializer_? - ; - -newPlacement - : LeftParen expressionList RightParen - ; - -newTypeId - : typeSpecifierSeq newDeclarator_? - ; - -newDeclarator_ - : pointerOperator newDeclarator_? - | noPointerNewDeclarator - ; - -noPointerNewDeclarator - : LeftBracket expression RightBracket attributeSpecifierSeq? - | noPointerNewDeclarator LeftBracket constantExpression RightBracket attributeSpecifierSeq? - ; - -newInitializer_ - : LeftParen expressionList? RightParen - | bracedInitList - ; - -deleteExpression - : Doublecolon? Delete (LeftBracket RightBracket)? castExpression - ; - -noExceptExpression - : Noexcept LeftParen expression RightParen - ; - -castExpression - : unaryExpression - | LeftParen theTypeId RightParen castExpression - ; - -pointerMemberExpression - : castExpression ((DotStar | ArrowStar) castExpression)* - ; - -multiplicativeExpression - : pointerMemberExpression ((Star | Div | Mod) pointerMemberExpression)* - ; - -additiveExpression - : multiplicativeExpression ((Plus | Minus) multiplicativeExpression)* - ; - -shiftExpression - : additiveExpression (shiftOperator additiveExpression)* - ; - -shiftOperator - : Greater Greater - | Less Less - ; - -relationalExpression - : shiftExpression ((Less | Greater | LessEqual | GreaterEqual) shiftExpression)* - ; - -equalityExpression - : relationalExpression ((Equal | NotEqual) relationalExpression)* - ; - -andExpression - : equalityExpression (And equalityExpression)* - ; - -exclusiveOrExpression - : andExpression (Caret andExpression)* - ; - -inclusiveOrExpression - : exclusiveOrExpression (Or exclusiveOrExpression)* - ; - -logicalAndExpression - : inclusiveOrExpression (AndAnd inclusiveOrExpression)* - ; - -logicalOrExpression - : logicalAndExpression (OrOr logicalAndExpression)* - ; - -conditionalExpression - : logicalOrExpression (Question expression Colon assignmentExpression)? - ; - -assignmentExpression - : conditionalExpression - | logicalOrExpression assignmentOperator initializerClause - | throwExpression - ; - -assignmentOperator - : Assign - | StarAssign - | DivAssign - | ModAssign - | PlusAssign - | MinusAssign - | RightShiftAssign - | LeftShiftAssign - | AndAssign - | XorAssign - | OrAssign - ; - -expression - : assignmentExpression (Comma assignmentExpression)* - ; - -constantExpression - : conditionalExpression - ; - -/*Statements*/ - -statement - : labeledStatement - | declarationStatement - | attributeSpecifierSeq? ( - expressionStatement - | compoundStatement - | selectionStatement - | iterationStatement - | jumpStatement - | tryBlock - ) - ; - -labeledStatement - : attributeSpecifierSeq? (Identifier | Case constantExpression | Default) Colon statement - ; - -expressionStatement - : expression? Semi - ; - -compoundStatement - : LeftBrace statementSeq? RightBrace - ; - -statementSeq - : statement+ - ; - -selectionStatement - : If LeftParen condition RightParen statement (Else statement)? - | Switch LeftParen condition RightParen statement - ; - -condition - : expression - | attributeSpecifierSeq? declSpecifierSeq declarator ( - Assign initializerClause - | bracedInitList - ) - ; - -iterationStatement - : While LeftParen condition RightParen statement - | Do statement While LeftParen expression RightParen Semi - | For LeftParen ( - forInitStatement condition? Semi expression? - | forRangeDeclaration Colon forRangeInitializer - ) RightParen statement - ; - -forInitStatement - : expressionStatement - | simpleDeclaration - ; - -forRangeDeclaration - : attributeSpecifierSeq? declSpecifierSeq declarator - ; - -forRangeInitializer - : expression - | bracedInitList - ; - -jumpStatement - : (Break | Continue | Return (expression | bracedInitList)? | Goto Identifier) Semi - ; - -declarationStatement - : blockDeclaration - ; - -/*Declarations*/ - -declarationSeq - : declaration+ - ; - -declaration - : blockDeclaration - | functionDefinition - | templateDeclaration - | explicitInstantiation - | explicitSpecialization - | linkageSpecification - | namespaceDefinition - | emptyDeclaration_ - | attributeDeclaration - ; - -blockDeclaration - : simpleDeclaration - | asmDefinition - | namespaceAliasDefinition - | usingDeclaration - | usingDirective - | staticAssertDeclaration - | aliasDeclaration - | opaqueEnumDeclaration - ; - -aliasDeclaration - : Using Identifier attributeSpecifierSeq? Assign theTypeId Semi - ; - -simpleDeclaration - : declSpecifierSeq? initDeclaratorList? Semi - | attributeSpecifierSeq declSpecifierSeq? initDeclaratorList Semi - ; - -staticAssertDeclaration - : Static_assert LeftParen constantExpression Comma StringLiteral RightParen Semi - ; - -emptyDeclaration_ - : Semi - ; - -attributeDeclaration - : attributeSpecifierSeq Semi - ; - -declSpecifier - : storageClassSpecifier - | typeSpecifier - | functionSpecifier - | Friend - | Typedef - | Constexpr - ; - -declSpecifierSeq - : declSpecifier+? attributeSpecifierSeq? - ; - -storageClassSpecifier - : Register - | Static - | Thread_local - | Extern - | Mutable - ; - -functionSpecifier - : Inline - | Virtual - | Explicit - ; - -typedefName - : Identifier - ; - -typeSpecifier - : trailingTypeSpecifier - | classSpecifier - | enumSpecifier - ; - -trailingTypeSpecifier - : simpleTypeSpecifier - | elaboratedTypeSpecifier - | typeNameSpecifier - | cvQualifier - ; - -typeSpecifierSeq - : typeSpecifier+ attributeSpecifierSeq? - ; - -trailingTypeSpecifierSeq - : trailingTypeSpecifier+ attributeSpecifierSeq? - ; - -simpleTypeLengthModifier - : Short - | Long - ; - -simpleTypeSignednessModifier - : Unsigned - | Signed - ; - -simpleTypeSpecifier - : nestedNameSpecifier? theTypeName - | nestedNameSpecifier Template simpleTemplateId - | Char - | Char16 - | Char32 - | Wchar - | Bool - | Short - | Int - | Long - | Float - | Signed - | Unsigned - | Float - | Double - | Void - | Auto - | decltypeSpecifier - ; - -theTypeName - : className - | enumName - | typedefName - | simpleTemplateId - ; - -decltypeSpecifier - : Decltype LeftParen (expression | Auto) RightParen - ; - -elaboratedTypeSpecifier - : classKey ( - attributeSpecifierSeq? nestedNameSpecifier? Identifier - | simpleTemplateId - | nestedNameSpecifier Template? simpleTemplateId - ) - | Enum nestedNameSpecifier? Identifier - ; - -enumName - : Identifier - ; - -enumSpecifier - : enumHead LeftBrace (enumeratorList Comma?)? RightBrace - ; - -enumHead - : enumKey attributeSpecifierSeq? (nestedNameSpecifier? Identifier)? enumBase? - ; - -opaqueEnumDeclaration - : enumKey attributeSpecifierSeq? Identifier enumBase? Semi - ; - -enumKey - : Enum (Class | Struct)? - ; - -enumBase - : Colon typeSpecifierSeq - ; - -enumeratorList - : enumeratorDefinition (Comma enumeratorDefinition)* - ; - -enumeratorDefinition - : enumerator (Assign constantExpression)? - ; - -enumerator - : Identifier - ; - -namespaceName - : originalNamespaceName - | namespaceAlias - ; - -originalNamespaceName - : Identifier - ; - -namespaceDefinition - : Inline? Namespace (Identifier | originalNamespaceName)? LeftBrace namespaceBody = declarationSeq? RightBrace - ; - -namespaceAlias - : Identifier - ; - -namespaceAliasDefinition - : Namespace Identifier Assign qualifiedNamespaceSpecifier Semi - ; - -qualifiedNamespaceSpecifier - : nestedNameSpecifier? namespaceName - ; - -usingDeclaration - : Using (Typename_? nestedNameSpecifier | Doublecolon) unqualifiedId Semi - ; - -usingDirective - : attributeSpecifierSeq? Using Namespace nestedNameSpecifier? namespaceName Semi - ; - -asmDefinition - : Asm LeftParen StringLiteral RightParen Semi - ; - -linkageSpecification - : Extern StringLiteral (LeftBrace declarationSeq? RightBrace | declaration) - ; - -attributeSpecifierSeq - : attributeSpecifier+ - ; - -attributeSpecifier - : LeftBracket LeftBracket attributeList? RightBracket RightBracket - | alignmentSpecifier - ; - -alignmentSpecifier - : Alignas LeftParen (theTypeId | constantExpression) Ellipsis? RightParen - ; - -attributeList - : attribute (Comma attribute)* Ellipsis? - ; - -attribute - : (attributeNamespace Doublecolon)? Identifier attributeArgumentClause? - ; - -attributeNamespace - : Identifier - ; - -attributeArgumentClause - : LeftParen balancedTokenSeq? RightParen - ; - -balancedTokenSeq - : balancedToken+ - ; - -balancedToken - : LeftParen balancedTokenSeq RightParen - | LeftBracket balancedTokenSeq RightBracket - | LeftBrace balancedTokenSeq RightBrace - | ~(LeftParen | RightParen | LeftBrace | RightBrace | LeftBracket | RightBracket)+ - ; - -/*Declarators*/ - -initDeclaratorList - : initDeclarator (Comma initDeclarator)* - ; - -initDeclarator - : declarator initializer? - ; - -declarator - : pointerDeclarator - | noPointerDeclarator parametersAndQualifiers trailingReturnType - ; - -pointerDeclarator - : (pointerOperator Const?)* noPointerDeclarator - ; - -noPointerDeclarator - : declaratorId attributeSpecifierSeq? - | noPointerDeclarator ( - parametersAndQualifiers - | LeftBracket constantExpression? RightBracket attributeSpecifierSeq? - ) - | LeftParen pointerDeclarator RightParen - ; - -parametersAndQualifiers - : LeftParen parameterDeclarationClause? RightParen cvQualifierSeq? refQualifier? exceptionSpecification? attributeSpecifierSeq? - ; - -trailingReturnType - : Arrow trailingTypeSpecifierSeq abstractDeclarator? - ; - -pointerOperator - : (And | AndAnd) attributeSpecifierSeq? - | nestedNameSpecifier? Star attributeSpecifierSeq? cvQualifierSeq? - ; - -cvQualifierSeq - : cvQualifier+ - ; - -cvQualifier - : Const - | Volatile - ; - -refQualifier - : And - | AndAnd - ; - -declaratorId - : Ellipsis? idExpression - ; - -theTypeId - : typeSpecifierSeq abstractDeclarator? - ; - -abstractDeclarator - : pointerAbstractDeclarator - | noPointerAbstractDeclarator? parametersAndQualifiers trailingReturnType - | abstractPackDeclarator - ; - -pointerAbstractDeclarator - : pointerOperator* (noPointerAbstractDeclarator | pointerOperator) - ; - -noPointerAbstractDeclarator - : (parametersAndQualifiers | LeftParen pointerAbstractDeclarator RightParen) ( - parametersAndQualifiers - | LeftBracket constantExpression? RightBracket attributeSpecifierSeq? - )* - ; - -abstractPackDeclarator - : pointerOperator* noPointerAbstractPackDeclarator - ; - -noPointerAbstractPackDeclarator - : Ellipsis ( - parametersAndQualifiers - | LeftBracket constantExpression? RightBracket attributeSpecifierSeq? - )* - ; - -parameterDeclarationClause - : parameterDeclarationList (Comma? Ellipsis)? - ; - -parameterDeclarationList - : parameterDeclaration (Comma parameterDeclaration)* - ; - -parameterDeclaration - : attributeSpecifierSeq? declSpecifierSeq (declarator | abstractDeclarator?) ( - Assign initializerClause - )? - ; - -functionDefinition - : attributeSpecifierSeq? declSpecifierSeq? declarator virtualSpecifierSeq? functionBody - ; - -functionBody - : constructorInitializer? compoundStatement - | functionTryBlock - | Assign (Default | Delete) Semi - ; - -initializer - : braceOrEqualInitializer - | LeftParen expressionList RightParen - ; - -braceOrEqualInitializer - : Assign initializerClause - | bracedInitList - ; - -initializerClause - : assignmentExpression - | bracedInitList - ; - -initializerList - : initializerClause Ellipsis? (Comma initializerClause Ellipsis?)* - ; - -bracedInitList - : LeftBrace (initializerList Comma?)? RightBrace - ; - -/*Classes*/ - -className - : Identifier - | simpleTemplateId - ; - -classSpecifier - : classHead LeftBrace memberSpecification? RightBrace - ; - -classHead - : classKey attributeSpecifierSeq? (classHeadName classVirtSpecifier?)? baseClause? - | Union attributeSpecifierSeq? ( classHeadName classVirtSpecifier?)? - ; - -classHeadName - : nestedNameSpecifier? className - ; - -classVirtSpecifier - : Final - ; - -classKey - : Class - | Struct - ; - -memberSpecification - : (memberDeclaration | accessSpecifier Colon)+ - ; - -memberDeclaration - : attributeSpecifierSeq? declSpecifierSeq? memberDeclaratorList? Semi - | functionDefinition - | usingDeclaration - | staticAssertDeclaration - | templateDeclaration - | aliasDeclaration - | emptyDeclaration_ - ; - -memberDeclaratorList - : memberDeclarator (Comma memberDeclarator)* - ; - -memberDeclarator - : declarator ( - virtualSpecifierSeq - | { this.IsPureSpecifierAllowed() }? pureSpecifier - | { this.IsPureSpecifierAllowed() }? virtualSpecifierSeq pureSpecifier - | braceOrEqualInitializer - ) - | declarator - | Identifier? attributeSpecifierSeq? Colon constantExpression - ; - -virtualSpecifierSeq - : virtualSpecifier+ - ; - -virtualSpecifier - : Override - | Final - ; - -/* - purespecifier: Assign '0'//Conflicts with the lexer ; - */ - -pureSpecifier - : Assign IntegerLiteral - ; - -/*Derived classes*/ - -baseClause - : Colon baseSpecifierList - ; - -baseSpecifierList - : baseSpecifier Ellipsis? (Comma baseSpecifier Ellipsis?)* - ; - -baseSpecifier - : attributeSpecifierSeq? ( - baseTypeSpecifier - | Virtual accessSpecifier? baseTypeSpecifier - | accessSpecifier Virtual? baseTypeSpecifier - ) - ; - -classOrDeclType - : nestedNameSpecifier? className - | decltypeSpecifier - ; - -baseTypeSpecifier - : classOrDeclType - ; - -accessSpecifier - : Private - | Protected - | Public - ; - -/*Special member functions*/ - -conversionFunctionId - : Operator conversionTypeId - ; - -conversionTypeId - : typeSpecifierSeq conversionDeclarator? - ; - -conversionDeclarator - : pointerOperator conversionDeclarator? - ; - -constructorInitializer - : Colon memInitializerList - ; - -memInitializerList - : memInitializer Ellipsis? (Comma memInitializer Ellipsis?)* - ; - -memInitializer - : memInitializerId (LeftParen expressionList? RightParen | bracedInitList) - ; - -memInitializerId - : classOrDeclType - | Identifier - ; - -/*Overloading*/ - -operatorFunctionId - : Operator theOperator - ; - -literalOperatorId - : Operator (StringLiteral Identifier | UserDefinedStringLiteral) - ; - -/*Templates*/ - -templateDeclaration - : Template Less templateParameterList Greater declaration - ; - -templateParameterList - : templateParameter (Comma templateParameter)* - ; - -templateParameter - : typeParameter - | parameterDeclaration - ; - -typeParameter - : ((Template Less templateParameterList Greater)? Class | Typename_) ( - Ellipsis? Identifier? - | Identifier? Assign theTypeId - ) - ; - -simpleTemplateId - : templateName Less templateArgumentList? Greater - ; - -templateId - : simpleTemplateId - | (operatorFunctionId | literalOperatorId) Less templateArgumentList? Greater - ; - -templateName - : Identifier - ; - -templateArgumentList - : templateArgument Ellipsis? (Comma templateArgument Ellipsis?)* - ; - -templateArgument - : theTypeId - | constantExpression - | idExpression - ; - -typeNameSpecifier - : Typename_ nestedNameSpecifier (Identifier | Template? simpleTemplateId) - ; - -explicitInstantiation - : Extern? Template declaration - ; - -explicitSpecialization - : Template Less Greater declaration - ; - -/*Exception handling*/ - -tryBlock - : Try compoundStatement handlerSeq - ; - -functionTryBlock - : Try constructorInitializer? compoundStatement handlerSeq - ; - -handlerSeq - : handler+ - ; - -handler - : Catch LeftParen exceptionDeclaration RightParen compoundStatement - ; - -exceptionDeclaration - : attributeSpecifierSeq? typeSpecifierSeq (declarator | abstractDeclarator)? - | Ellipsis - ; - -throwExpression - : Throw assignmentExpression? - ; - -exceptionSpecification - : dynamicExceptionSpecification - | noExceptSpecification - ; - -dynamicExceptionSpecification - : Throw LeftParen typeIdList? RightParen - ; - -typeIdList - : theTypeId Ellipsis? (Comma theTypeId Ellipsis?)* - ; - -noExceptSpecification - : Noexcept LeftParen constantExpression RightParen - | Noexcept - ; - -/*Preprocessing directives*/ - -/*Lexer*/ - -theOperator - : New (LeftBracket RightBracket)? - | Delete (LeftBracket RightBracket)? - | Plus - | Minus - | Star - | Div - | Mod - | Caret - | And - | Or - | Tilde - | Not - | Assign - | Greater - | Less - | GreaterEqual - | PlusAssign - | MinusAssign - | StarAssign - | ModAssign - | XorAssign - | AndAssign - | OrAssign - | Less Less - | Greater Greater - | RightShiftAssign - | LeftShiftAssign - | Equal - | NotEqual - | LessEqual - | AndAnd - | OrOr - | PlusPlus - | MinusMinus - | Comma - | ArrowStar - | Arrow - | LeftParen RightParen - | LeftBracket RightBracket - ; - -literal - : IntegerLiteral - | CharacterLiteral - | FloatingLiteral - | StringLiteral - | BooleanLiteral - | PointerLiteral - | UserDefinedLiteral - ; - diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpLexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpLexer.g4 deleted file mode 100644 index 8ec5d774..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpLexer.g4 +++ /dev/null @@ -1,1059 +0,0 @@ -// Eclipse Public License - v 1.0, http://www.eclipse.org/legal/epl-v10.html -// Copyright (c) 2013, Christian Wulf (chwchw@gmx.de) -// Copyright (c) 2016-2017, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies. - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar CSharpLexer; - -channels { - COMMENTS_CHANNEL, - DIRECTIVE -} - -options { - superClass = CSharpLexerBase; -} - -BYTE_ORDER_MARK: '\u00EF\u00BB\u00BF'; - -SINGLE_LINE_DOC_COMMENT : '///' InputCharacter* -> channel(COMMENTS_CHANNEL); -EMPTY_DELIMITED_DOC_COMMENT : '/***/' -> channel(COMMENTS_CHANNEL); -DELIMITED_DOC_COMMENT : '/**' ~'/' .*? '*/' -> channel(COMMENTS_CHANNEL); -SINGLE_LINE_COMMENT : '//' InputCharacter* -> channel(COMMENTS_CHANNEL); -DELIMITED_COMMENT : '/*' .*? '*/' -> channel(COMMENTS_CHANNEL); -WHITESPACES : (Whitespace | NewLine)+ -> channel(HIDDEN); -SHARP : '#' -> mode(DIRECTIVE_MODE), skip; - -ABSTRACT : 'abstract'; -ADD : 'add'; -ALIAS : 'alias'; -ARGLIST : '__arglist'; -AS : 'as'; -ASCENDING : 'ascending'; -ASYNC : 'async'; -AWAIT : 'await'; -BASE : 'base'; -BOOL : 'bool'; -BREAK : 'break'; -BY : 'by'; -BYTE : 'byte'; -CASE : 'case'; -CATCH : 'catch'; -CHAR : 'char'; -CHECKED : 'checked'; -CLASS : 'class'; -CONST : 'const'; -CONTINUE : 'continue'; -DECIMAL : 'decimal'; -DEFAULT : 'default'; -DELEGATE : 'delegate'; -DESCENDING : 'descending'; -DO : 'do'; -DOUBLE : 'double'; -DYNAMIC : 'dynamic'; -ELSE : 'else'; -ENUM : 'enum'; -EQUALS : 'equals'; -EVENT : 'event'; -EXPLICIT : 'explicit'; -EXTERN : 'extern'; -FALSE : 'false'; -FINALLY : 'finally'; -FIXED : 'fixed'; -FLOAT : 'float'; -FOR : 'for'; -FOREACH : 'foreach'; -FROM : 'from'; -GET : 'get'; -GOTO : 'goto'; -GROUP : 'group'; -IF : 'if'; -IMPLICIT : 'implicit'; -IN : 'in'; -INT : 'int'; -INTERFACE : 'interface'; -INTERNAL : 'internal'; -INTO : 'into'; -IS : 'is'; -JOIN : 'join'; -LET : 'let'; -LOCK : 'lock'; -LONG : 'long'; -NAMEOF : 'nameof'; -NAMESPACE : 'namespace'; -NEW : 'new'; -NULL_ : 'null'; -OBJECT : 'object'; -ON : 'on'; -OPERATOR : 'operator'; -ORDERBY : 'orderby'; -OUT : 'out'; -OVERRIDE : 'override'; -PARAMS : 'params'; -PARTIAL : 'partial'; -PRIVATE : 'private'; -PROTECTED : 'protected'; -PUBLIC : 'public'; -READONLY : 'readonly'; -REF : 'ref'; -REMOVE : 'remove'; -RETURN : 'return'; -SBYTE : 'sbyte'; -SEALED : 'sealed'; -SELECT : 'select'; -SET : 'set'; -SHORT : 'short'; -SIZEOF : 'sizeof'; -STACKALLOC : 'stackalloc'; -STATIC : 'static'; -STRING : 'string'; -STRUCT : 'struct'; -SWITCH : 'switch'; -THIS : 'this'; -THROW : 'throw'; -TRUE : 'true'; -TRY : 'try'; -TYPEOF : 'typeof'; -UINT : 'uint'; -ULONG : 'ulong'; -UNCHECKED : 'unchecked'; -UNMANAGED : 'unmanaged'; -UNSAFE : 'unsafe'; -USHORT : 'ushort'; -USING : 'using'; -VAR : 'var'; -VIRTUAL : 'virtual'; -VOID : 'void'; -VOLATILE : 'volatile'; -WHEN : 'when'; -WHERE : 'where'; -WHILE : 'while'; -YIELD : 'yield'; - -//B.1.6 Identifiers -// must be defined after all keywords so the first branch (Available_identifier) does not match keywords -// https://msdn.microsoft.com/en-us/library/aa664670(v=vs.71).aspx -IDENTIFIER: '@'? IdentifierOrKeyword; - -//B.1.8 Literals -// 0.Equals() would be parsed as an invalid real (1. branch) causing a lexer error -// Note: '_'* digit separators in numeric literals: C# 7.0 -LITERAL_ACCESS : [0-9] ('_'* [0-9])* IntegerTypeSuffix? '.' '@'? IdentifierOrKeyword; -INTEGER_LITERAL : [0-9] ('_'* [0-9])* IntegerTypeSuffix?; -HEX_INTEGER_LITERAL : '0' [xX] ('_'* HexDigit)+ IntegerTypeSuffix?; -BIN_INTEGER_LITERAL : '0' [bB] ('_'* [01])+ IntegerTypeSuffix?; // C# 7.0 -REAL_LITERAL: - ([0-9] ('_'* [0-9])*)? '.' [0-9] ('_'* [0-9])* ExponentPart? [FfDdMm]? - | [0-9] ('_'* [0-9])* ([FfDdMm] | ExponentPart [FfDdMm]?) -; - -CHARACTER_LITERAL : '\'' (~['\\\r\n\u0085\u2028\u2029] | CommonCharacter) '\''; -REGULAR_STRING : '"' (~["\\\r\n\u0085\u2028\u2029] | CommonCharacter)* '"'; -VERBATIUM_STRING : '@"' (~'"' | '""')* '"'; -INTERPOLATED_REGULAR_STRING_START: - '$"' { this.OnInterpolatedRegularStringStart(); } -> pushMode(INTERPOLATION_STRING) -; -INTERPOLATED_VERBATIUM_STRING_START: - '$@"' { this.OnInterpolatedVerbatiumStringStart(); } -> pushMode(INTERPOLATION_STRING) -; - -//B.1.9 Operators And Punctuators -OPEN_BRACE : '{' { this.OnOpenBrace(); }; -CLOSE_BRACE : '}' { this.OnCloseBrace(); }; -OPEN_BRACKET : '['; -CLOSE_BRACKET : ']'; -OPEN_PARENS : '('; -CLOSE_PARENS : ')'; -DOT : '.'; -COMMA : ','; -COLON : ':' { this.OnColon(); }; -SEMICOLON : ';'; -PLUS : '+'; -MINUS : '-'; -STAR : '*'; -DIV : '/'; -PERCENT : '%'; -AMP : '&'; -BITWISE_OR : '|'; -CARET : '^'; -BANG : '!'; -TILDE : '~'; -ASSIGNMENT : '='; -LT : '<'; -GT : '>'; -INTERR : '?'; -DOUBLE_COLON : '::'; -OP_COALESCING : '??'; -OP_INC : '++'; -OP_DEC : '--'; -OP_AND : '&&'; -OP_OR : '||'; -OP_PTR : '->'; -OP_EQ : '=='; -OP_NE : '!='; -OP_LE : '<='; -OP_GE : '>='; -OP_ADD_ASSIGNMENT : '+='; -OP_SUB_ASSIGNMENT : '-='; -OP_MULT_ASSIGNMENT : '*='; -OP_DIV_ASSIGNMENT : '/='; -OP_MOD_ASSIGNMENT : '%='; -OP_AND_ASSIGNMENT : '&='; -OP_OR_ASSIGNMENT : '|='; -OP_XOR_ASSIGNMENT : '^='; -OP_LEFT_SHIFT : '<<'; -OP_LEFT_SHIFT_ASSIGNMENT : '<<='; -OP_COALESCING_ASSIGNMENT : '??='; // C# 8.0 -OP_RANGE : '..'; // C# 8.0 - -// https://msdn.microsoft.com/en-us/library/dn961160.aspx -mode INTERPOLATION_STRING; - -DOUBLE_CURLY_INSIDE : '{{'; -OPEN_BRACE_INSIDE : '{' { this.OpenBraceInside(); } -> skip, pushMode(DEFAULT_MODE); -REGULAR_CHAR_INSIDE : { this.IsRegularCharInside() }? SimpleEscapeSequence; -VERBATIUM_DOUBLE_QUOTE_INSIDE : { this.IsVerbatiumDoubleQuoteInside() }? '""'; -DOUBLE_QUOTE_INSIDE : '"' { this.OnDoubleQuoteInside(); } -> popMode; -REGULAR_STRING_INSIDE : { this.IsRegularCharInside() }? ~('{' | '\\' | '"')+; -VERBATIUM_INSIDE_STRING : { this.IsVerbatiumDoubleQuoteInside() }? ~('{' | '"')+; - -mode INTERPOLATION_FORMAT; - -DOUBLE_CURLY_CLOSE_INSIDE : '}}' -> type(FORMAT_STRING); -CLOSE_BRACE_INSIDE : '}' { this.OnCloseBraceInside(); } -> skip, popMode; -FORMAT_STRING : ~'}'+; - -mode DIRECTIVE_MODE; - -DIRECTIVE_WHITESPACES : Whitespace+ -> channel(HIDDEN); -DIGITS : [0-9]+ -> channel(DIRECTIVE); -DIRECTIVE_TRUE : 'true' -> channel(DIRECTIVE), type(TRUE); -DIRECTIVE_FALSE : 'false' -> channel(DIRECTIVE), type(FALSE); -DEFINE : 'define' -> channel(DIRECTIVE); -UNDEF : 'undef' -> channel(DIRECTIVE); -DIRECTIVE_IF : 'if' -> channel(DIRECTIVE), type(IF); -ELIF : 'elif' -> channel(DIRECTIVE); -DIRECTIVE_ELSE : 'else' -> channel(DIRECTIVE), type(ELSE); -ENDIF : 'endif' -> channel(DIRECTIVE); -LINE : 'line' -> channel(DIRECTIVE); -ERROR : 'error' Whitespace+ -> channel(DIRECTIVE), mode(DIRECTIVE_TEXT); -WARNING : 'warning' Whitespace+ -> channel(DIRECTIVE), mode(DIRECTIVE_TEXT); -REGION : 'region' Whitespace* -> channel(DIRECTIVE), mode(DIRECTIVE_TEXT); -ENDREGION : 'endregion' Whitespace* -> channel(DIRECTIVE), mode(DIRECTIVE_TEXT); -PRAGMA : 'pragma' Whitespace+ -> channel(DIRECTIVE), mode(DIRECTIVE_TEXT); -NULLABLE : 'nullable' Whitespace+ -> channel(DIRECTIVE), mode(DIRECTIVE_TEXT); // C# 8.0 -DIRECTIVE_DEFAULT : 'default' -> channel(DIRECTIVE), type(DEFAULT); -DIRECTIVE_HIDDEN : 'hidden' -> channel(DIRECTIVE); -DIRECTIVE_OPEN_PARENS : '(' -> channel(DIRECTIVE), type(OPEN_PARENS); -DIRECTIVE_CLOSE_PARENS : ')' -> channel(DIRECTIVE), type(CLOSE_PARENS); -DIRECTIVE_BANG : '!' -> channel(DIRECTIVE), type(BANG); -DIRECTIVE_OP_EQ : '==' -> channel(DIRECTIVE), type(OP_EQ); -DIRECTIVE_OP_NE : '!=' -> channel(DIRECTIVE), type(OP_NE); -DIRECTIVE_OP_AND : '&&' -> channel(DIRECTIVE), type(OP_AND); -DIRECTIVE_OP_OR : '||' -> channel(DIRECTIVE), type(OP_OR); -DIRECTIVE_STRING: - '"' ~('"' | [\r\n\u0085\u2028\u2029])* '"' -> channel(DIRECTIVE), type(STRING) -; -CONDITIONAL_SYMBOL: IdentifierOrKeyword -> channel(DIRECTIVE); -DIRECTIVE_SINGLE_LINE_COMMENT: - '//' ~[\r\n\u0085\u2028\u2029]* -> channel(COMMENTS_CHANNEL), type(SINGLE_LINE_COMMENT) -; -DIRECTIVE_NEW_LINE: NewLine -> channel(DIRECTIVE), mode(DEFAULT_MODE); - -mode DIRECTIVE_TEXT; - -TEXT : ~[\r\n\u0085\u2028\u2029]+ -> channel(DIRECTIVE); -TEXT_NEW_LINE : NewLine -> channel(DIRECTIVE), type(DIRECTIVE_NEW_LINE), mode(DEFAULT_MODE); - -// Fragments - -fragment InputCharacter: ~[\r\n\u0085\u2028\u2029]; - -fragment NewLineCharacter: - '\u000D' //'' - | '\u000A' //'' - | '\u0085' //'' - | '\u2028' //'' - | '\u2029' //'' -; - -fragment IntegerTypeSuffix : [lL]? [uU] | [uU]? [lL]; -fragment ExponentPart : [eE] ('+' | '-')? [0-9] ('_'* [0-9])*; - -fragment CommonCharacter: SimpleEscapeSequence | HexEscapeSequence | UnicodeEscapeSequence; - -fragment SimpleEscapeSequence: - '\\\'' - | '\\"' - | '\\\\' - | '\\0' - | '\\a' - | '\\b' - | '\\f' - | '\\n' - | '\\r' - | '\\t' - | '\\v' -; - -fragment HexEscapeSequence: - '\\x' HexDigit - | '\\x' HexDigit HexDigit - | '\\x' HexDigit HexDigit HexDigit - | '\\x' HexDigit HexDigit HexDigit HexDigit -; - -fragment NewLine: - '\r\n' - | '\r' - | '\n' - | '\u0085' // ' - | '\u2028' //'' - | '\u2029' //'' -; - -fragment Whitespace: - UnicodeClassZS //'' - | '\u0009' //'' - | '\u000B' //'' - | '\u000C' //'
' -; - -fragment UnicodeClassZS: - '\u0020' // SPACE - | '\u00A0' // NO_BREAK SPACE - | '\u1680' // OGHAM SPACE MARK - | '\u180E' // MONGOLIAN VOWEL SEPARATOR - | '\u2000' // EN QUAD - | '\u2001' // EM QUAD - | '\u2002' // EN SPACE - | '\u2003' // EM SPACE - | '\u2004' // THREE_PER_EM SPACE - | '\u2005' // FOUR_PER_EM SPACE - | '\u2006' // SIX_PER_EM SPACE - | '\u2008' // PUNCTUATION SPACE - | '\u2009' // THIN SPACE - | '\u200A' // HAIR SPACE - | '\u202F' // NARROW NO_BREAK SPACE - | '\u3000' // IDEOGRAPHIC SPACE - | '\u205F' // MEDIUM MATHEMATICAL SPACE -; - -fragment IdentifierOrKeyword: IdentifierStartCharacter IdentifierPartCharacter*; - -fragment IdentifierStartCharacter: LetterCharacter | '_'; - -fragment IdentifierPartCharacter: - LetterCharacter - | DecimalDigitCharacter - | ConnectingCharacter - | CombiningCharacter - | FormattingCharacter -; - -//'' -// WARNING: ignores UnicodeEscapeSequence -fragment LetterCharacter: - UnicodeClassLU - | UnicodeClassLL - | UnicodeClassLT - | UnicodeClassLM - | UnicodeClassLO - | UnicodeClassNL - | UnicodeEscapeSequence -; - -//'' -// WARNING: ignores UnicodeEscapeSequence -fragment DecimalDigitCharacter: UnicodeClassND | UnicodeEscapeSequence; - -//'' -// WARNING: ignores UnicodeEscapeSequence -fragment ConnectingCharacter: UnicodeClassPC | UnicodeEscapeSequence; - -//'' -// WARNING: ignores UnicodeEscapeSequence -fragment CombiningCharacter: UnicodeClassMN | UnicodeClassMC | UnicodeEscapeSequence; - -//'' -// WARNING: ignores UnicodeEscapeSequence -fragment FormattingCharacter: UnicodeClassCF | UnicodeEscapeSequence; - -//B.1.5 Unicode Character Escape Sequences -fragment UnicodeEscapeSequence: - '\\u' HexDigit HexDigit HexDigit HexDigit - | '\\U' HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit -; - -fragment HexDigit: [0-9] | [A-F] | [a-f]; - -// Unicode character classes -fragment UnicodeClassLU: - '\u0041' ..'\u005a' - | '\u00c0' ..'\u00d6' - | '\u00d8' ..'\u00de' - | '\u0100' ..'\u0136' - | '\u0139' ..'\u0147' - | '\u014a' ..'\u0178' - | '\u0179' ..'\u017d' - | '\u0181' ..'\u0182' - | '\u0184' ..'\u0186' - | '\u0187' ..'\u0189' - | '\u018a' ..'\u018b' - | '\u018e' ..'\u0191' - | '\u0193' ..'\u0194' - | '\u0196' ..'\u0198' - | '\u019c' ..'\u019d' - | '\u019f' ..'\u01a0' - | '\u01a2' ..'\u01a6' - | '\u01a7' ..'\u01a9' - | '\u01ac' ..'\u01ae' - | '\u01af' ..'\u01b1' - | '\u01b2' ..'\u01b3' - | '\u01b5' ..'\u01b7' - | '\u01b8' ..'\u01bc' - | '\u01c4' ..'\u01cd' - | '\u01cf' ..'\u01db' - | '\u01de' ..'\u01ee' - | '\u01f1' ..'\u01f4' - | '\u01f6' ..'\u01f8' - | '\u01fa' ..'\u0232' - | '\u023a' ..'\u023b' - | '\u023d' ..'\u023e' - | '\u0241' ..'\u0243' - | '\u0244' ..'\u0246' - | '\u0248' ..'\u024e' - | '\u0370' ..'\u0372' - | '\u0376' ..'\u037f' - | '\u0386' ..'\u0388' - | '\u0389' ..'\u038a' - | '\u038c' ..'\u038e' - | '\u038f' ..'\u0391' - | '\u0392' ..'\u03a1' - | '\u03a3' ..'\u03ab' - | '\u03cf' ..'\u03d2' - | '\u03d3' ..'\u03d4' - | '\u03d8' ..'\u03ee' - | '\u03f4' ..'\u03f7' - | '\u03f9' ..'\u03fa' - | '\u03fd' ..'\u042f' - | '\u0460' ..'\u0480' - | '\u048a' ..'\u04c0' - | '\u04c1' ..'\u04cd' - | '\u04d0' ..'\u052e' - | '\u0531' ..'\u0556' - | '\u10a0' ..'\u10c5' - | '\u10c7' ..'\u10cd' - | '\u1e00' ..'\u1e94' - | '\u1e9e' ..'\u1efe' - | '\u1f08' ..'\u1f0f' - | '\u1f18' ..'\u1f1d' - | '\u1f28' ..'\u1f2f' - | '\u1f38' ..'\u1f3f' - | '\u1f48' ..'\u1f4d' - | '\u1f59' ..'\u1f5f' - | '\u1f68' ..'\u1f6f' - | '\u1fb8' ..'\u1fbb' - | '\u1fc8' ..'\u1fcb' - | '\u1fd8' ..'\u1fdb' - | '\u1fe8' ..'\u1fec' - | '\u1ff8' ..'\u1ffb' - | '\u2102' ..'\u2107' - | '\u210b' ..'\u210d' - | '\u2110' ..'\u2112' - | '\u2115' ..'\u2119' - | '\u211a' ..'\u211d' - | '\u2124' ..'\u212a' - | '\u212b' ..'\u212d' - | '\u2130' ..'\u2133' - | '\u213e' ..'\u213f' - | '\u2145' ..'\u2183' - | '\u2c00' ..'\u2c2e' - | '\u2c60' ..'\u2c62' - | '\u2c63' ..'\u2c64' - | '\u2c67' ..'\u2c6d' - | '\u2c6e' ..'\u2c70' - | '\u2c72' ..'\u2c75' - | '\u2c7e' ..'\u2c80' - | '\u2c82' ..'\u2ce2' - | '\u2ceb' ..'\u2ced' - | '\u2cf2' ..'\ua640' - | '\ua642' ..'\ua66c' - | '\ua680' ..'\ua69a' - | '\ua722' ..'\ua72e' - | '\ua732' ..'\ua76e' - | '\ua779' ..'\ua77d' - | '\ua77e' ..'\ua786' - | '\ua78b' ..'\ua78d' - | '\ua790' ..'\ua792' - | '\ua796' ..'\ua7aa' - | '\ua7ab' ..'\ua7ad' - | '\ua7b0' ..'\ua7b1' - | '\uff21' ..'\uff3a' -; - -fragment UnicodeClassLL: - '\u0061' ..'\u007A' - | '\u00b5' ..'\u00df' - | '\u00e0' ..'\u00f6' - | '\u00f8' ..'\u00ff' - | '\u0101' ..'\u0137' - | '\u0138' ..'\u0148' - | '\u0149' ..'\u0177' - | '\u017a' ..'\u017e' - | '\u017f' ..'\u0180' - | '\u0183' ..'\u0185' - | '\u0188' ..'\u018c' - | '\u018d' ..'\u0192' - | '\u0195' ..'\u0199' - | '\u019a' ..'\u019b' - | '\u019e' ..'\u01a1' - | '\u01a3' ..'\u01a5' - | '\u01a8' ..'\u01aa' - | '\u01ab' ..'\u01ad' - | '\u01b0' ..'\u01b4' - | '\u01b6' ..'\u01b9' - | '\u01ba' ..'\u01bd' - | '\u01be' ..'\u01bf' - | '\u01c6' ..'\u01cc' - | '\u01ce' ..'\u01dc' - | '\u01dd' ..'\u01ef' - | '\u01f0' ..'\u01f3' - | '\u01f5' ..'\u01f9' - | '\u01fb' ..'\u0233' - | '\u0234' ..'\u0239' - | '\u023c' ..'\u023f' - | '\u0240' ..'\u0242' - | '\u0247' ..'\u024f' - | '\u0250' ..'\u0293' - | '\u0295' ..'\u02af' - | '\u0371' ..'\u0373' - | '\u0377' ..'\u037b' - | '\u037c' ..'\u037d' - | '\u0390' ..'\u03ac' - | '\u03ad' ..'\u03ce' - | '\u03d0' ..'\u03d1' - | '\u03d5' ..'\u03d7' - | '\u03d9' ..'\u03ef' - | '\u03f0' ..'\u03f3' - | '\u03f5' ..'\u03fb' - | '\u03fc' ..'\u0430' - | '\u0431' ..'\u045f' - | '\u0461' ..'\u0481' - | '\u048b' ..'\u04bf' - | '\u04c2' ..'\u04ce' - | '\u04cf' ..'\u052f' - | '\u0561' ..'\u0587' - | '\u1d00' ..'\u1d2b' - | '\u1d6b' ..'\u1d77' - | '\u1d79' ..'\u1d9a' - | '\u1e01' ..'\u1e95' - | '\u1e96' ..'\u1e9d' - | '\u1e9f' ..'\u1eff' - | '\u1f00' ..'\u1f07' - | '\u1f10' ..'\u1f15' - | '\u1f20' ..'\u1f27' - | '\u1f30' ..'\u1f37' - | '\u1f40' ..'\u1f45' - | '\u1f50' ..'\u1f57' - | '\u1f60' ..'\u1f67' - | '\u1f70' ..'\u1f7d' - | '\u1f80' ..'\u1f87' - | '\u1f90' ..'\u1f97' - | '\u1fa0' ..'\u1fa7' - | '\u1fb0' ..'\u1fb4' - | '\u1fb6' ..'\u1fb7' - | '\u1fbe' ..'\u1fc2' - | '\u1fc3' ..'\u1fc4' - | '\u1fc6' ..'\u1fc7' - | '\u1fd0' ..'\u1fd3' - | '\u1fd6' ..'\u1fd7' - | '\u1fe0' ..'\u1fe7' - | '\u1ff2' ..'\u1ff4' - | '\u1ff6' ..'\u1ff7' - | '\u210a' ..'\u210e' - | '\u210f' ..'\u2113' - | '\u212f' ..'\u2139' - | '\u213c' ..'\u213d' - | '\u2146' ..'\u2149' - | '\u214e' ..'\u2184' - | '\u2c30' ..'\u2c5e' - | '\u2c61' ..'\u2c65' - | '\u2c66' ..'\u2c6c' - | '\u2c71' ..'\u2c73' - | '\u2c74' ..'\u2c76' - | '\u2c77' ..'\u2c7b' - | '\u2c81' ..'\u2ce3' - | '\u2ce4' ..'\u2cec' - | '\u2cee' ..'\u2cf3' - | '\u2d00' ..'\u2d25' - | '\u2d27' ..'\u2d2d' - | '\ua641' ..'\ua66d' - | '\ua681' ..'\ua69b' - | '\ua723' ..'\ua72f' - | '\ua730' ..'\ua731' - | '\ua733' ..'\ua771' - | '\ua772' ..'\ua778' - | '\ua77a' ..'\ua77c' - | '\ua77f' ..'\ua787' - | '\ua78c' ..'\ua78e' - | '\ua791' ..'\ua793' - | '\ua794' ..'\ua795' - | '\ua797' ..'\ua7a9' - | '\ua7fa' ..'\uab30' - | '\uab31' ..'\uab5a' - | '\uab64' ..'\uab65' - | '\ufb00' ..'\ufb06' - | '\ufb13' ..'\ufb17' - | '\uff41' ..'\uff5a' -; - -fragment UnicodeClassLT: - '\u01c5' ..'\u01cb' - | '\u01f2' ..'\u1f88' - | '\u1f89' ..'\u1f8f' - | '\u1f98' ..'\u1f9f' - | '\u1fa8' ..'\u1faf' - | '\u1fbc' ..'\u1fcc' - | '\u1ffc' ..'\u1ffc' -; - -fragment UnicodeClassLM: - '\u02b0' ..'\u02c1' - | '\u02c6' ..'\u02d1' - | '\u02e0' ..'\u02e4' - | '\u02ec' ..'\u02ee' - | '\u0374' ..'\u037a' - | '\u0559' ..'\u0640' - | '\u06e5' ..'\u06e6' - | '\u07f4' ..'\u07f5' - | '\u07fa' ..'\u081a' - | '\u0824' ..'\u0828' - | '\u0971' ..'\u0e46' - | '\u0ec6' ..'\u10fc' - | '\u17d7' ..'\u1843' - | '\u1aa7' ..'\u1c78' - | '\u1c79' ..'\u1c7d' - | '\u1d2c' ..'\u1d6a' - | '\u1d78' ..'\u1d9b' - | '\u1d9c' ..'\u1dbf' - | '\u2071' ..'\u207f' - | '\u2090' ..'\u209c' - | '\u2c7c' ..'\u2c7d' - | '\u2d6f' ..'\u2e2f' - | '\u3005' ..'\u3031' - | '\u3032' ..'\u3035' - | '\u303b' ..'\u309d' - | '\u309e' ..'\u30fc' - | '\u30fd' ..'\u30fe' - | '\ua015' ..'\ua4f8' - | '\ua4f9' ..'\ua4fd' - | '\ua60c' ..'\ua67f' - | '\ua69c' ..'\ua69d' - | '\ua717' ..'\ua71f' - | '\ua770' ..'\ua788' - | '\ua7f8' ..'\ua7f9' - | '\ua9cf' ..'\ua9e6' - | '\uaa70' ..'\uaadd' - | '\uaaf3' ..'\uaaf4' - | '\uab5c' ..'\uab5f' - | '\uff70' ..'\uff9e' - | '\uff9f' ..'\uff9f' -; - -fragment UnicodeClassLO: - '\u00aa' ..'\u00ba' - | '\u01bb' ..'\u01c0' - | '\u01c1' ..'\u01c3' - | '\u0294' ..'\u05d0' - | '\u05d1' ..'\u05ea' - | '\u05f0' ..'\u05f2' - | '\u0620' ..'\u063f' - | '\u0641' ..'\u064a' - | '\u066e' ..'\u066f' - | '\u0671' ..'\u06d3' - | '\u06d5' ..'\u06ee' - | '\u06ef' ..'\u06fa' - | '\u06fb' ..'\u06fc' - | '\u06ff' ..'\u0710' - | '\u0712' ..'\u072f' - | '\u074d' ..'\u07a5' - | '\u07b1' ..'\u07ca' - | '\u07cb' ..'\u07ea' - | '\u0800' ..'\u0815' - | '\u0840' ..'\u0858' - | '\u08a0' ..'\u08b2' - | '\u0904' ..'\u0939' - | '\u093d' ..'\u0950' - | '\u0958' ..'\u0961' - | '\u0972' ..'\u0980' - | '\u0985' ..'\u098c' - | '\u098f' ..'\u0990' - | '\u0993' ..'\u09a8' - | '\u09aa' ..'\u09b0' - | '\u09b2' ..'\u09b6' - | '\u09b7' ..'\u09b9' - | '\u09bd' ..'\u09ce' - | '\u09dc' ..'\u09dd' - | '\u09df' ..'\u09e1' - | '\u09f0' ..'\u09f1' - | '\u0a05' ..'\u0a0a' - | '\u0a0f' ..'\u0a10' - | '\u0a13' ..'\u0a28' - | '\u0a2a' ..'\u0a30' - | '\u0a32' ..'\u0a33' - | '\u0a35' ..'\u0a36' - | '\u0a38' ..'\u0a39' - | '\u0a59' ..'\u0a5c' - | '\u0a5e' ..'\u0a72' - | '\u0a73' ..'\u0a74' - | '\u0a85' ..'\u0a8d' - | '\u0a8f' ..'\u0a91' - | '\u0a93' ..'\u0aa8' - | '\u0aaa' ..'\u0ab0' - | '\u0ab2' ..'\u0ab3' - | '\u0ab5' ..'\u0ab9' - | '\u0abd' ..'\u0ad0' - | '\u0ae0' ..'\u0ae1' - | '\u0b05' ..'\u0b0c' - | '\u0b0f' ..'\u0b10' - | '\u0b13' ..'\u0b28' - | '\u0b2a' ..'\u0b30' - | '\u0b32' ..'\u0b33' - | '\u0b35' ..'\u0b39' - | '\u0b3d' ..'\u0b5c' - | '\u0b5d' ..'\u0b5f' - | '\u0b60' ..'\u0b61' - | '\u0b71' ..'\u0b83' - | '\u0b85' ..'\u0b8a' - | '\u0b8e' ..'\u0b90' - | '\u0b92' ..'\u0b95' - | '\u0b99' ..'\u0b9a' - | '\u0b9c' ..'\u0b9e' - | '\u0b9f' ..'\u0ba3' - | '\u0ba4' ..'\u0ba8' - | '\u0ba9' ..'\u0baa' - | '\u0bae' ..'\u0bb9' - | '\u0bd0' ..'\u0c05' - | '\u0c06' ..'\u0c0c' - | '\u0c0e' ..'\u0c10' - | '\u0c12' ..'\u0c28' - | '\u0c2a' ..'\u0c39' - | '\u0c3d' ..'\u0c58' - | '\u0c59' ..'\u0c60' - | '\u0c61' ..'\u0c85' - | '\u0c86' ..'\u0c8c' - | '\u0c8e' ..'\u0c90' - | '\u0c92' ..'\u0ca8' - | '\u0caa' ..'\u0cb3' - | '\u0cb5' ..'\u0cb9' - | '\u0cbd' ..'\u0cde' - | '\u0ce0' ..'\u0ce1' - | '\u0cf1' ..'\u0cf2' - | '\u0d05' ..'\u0d0c' - | '\u0d0e' ..'\u0d10' - | '\u0d12' ..'\u0d3a' - | '\u0d3d' ..'\u0d4e' - | '\u0d60' ..'\u0d61' - | '\u0d7a' ..'\u0d7f' - | '\u0d85' ..'\u0d96' - | '\u0d9a' ..'\u0db1' - | '\u0db3' ..'\u0dbb' - | '\u0dbd' ..'\u0dc0' - | '\u0dc1' ..'\u0dc6' - | '\u0e01' ..'\u0e30' - | '\u0e32' ..'\u0e33' - | '\u0e40' ..'\u0e45' - | '\u0e81' ..'\u0e82' - | '\u0e84' ..'\u0e87' - | '\u0e88' ..'\u0e8a' - | '\u0e8d' ..'\u0e94' - | '\u0e95' ..'\u0e97' - | '\u0e99' ..'\u0e9f' - | '\u0ea1' ..'\u0ea3' - | '\u0ea5' ..'\u0ea7' - | '\u0eaa' ..'\u0eab' - | '\u0ead' ..'\u0eb0' - | '\u0eb2' ..'\u0eb3' - | '\u0ebd' ..'\u0ec0' - | '\u0ec1' ..'\u0ec4' - | '\u0edc' ..'\u0edf' - | '\u0f00' ..'\u0f40' - | '\u0f41' ..'\u0f47' - | '\u0f49' ..'\u0f6c' - | '\u0f88' ..'\u0f8c' - | '\u1000' ..'\u102a' - | '\u103f' ..'\u1050' - | '\u1051' ..'\u1055' - | '\u105a' ..'\u105d' - | '\u1061' ..'\u1065' - | '\u1066' ..'\u106e' - | '\u106f' ..'\u1070' - | '\u1075' ..'\u1081' - | '\u108e' ..'\u10d0' - | '\u10d1' ..'\u10fa' - | '\u10fd' ..'\u1248' - | '\u124a' ..'\u124d' - | '\u1250' ..'\u1256' - | '\u1258' ..'\u125a' - | '\u125b' ..'\u125d' - | '\u1260' ..'\u1288' - | '\u128a' ..'\u128d' - | '\u1290' ..'\u12b0' - | '\u12b2' ..'\u12b5' - | '\u12b8' ..'\u12be' - | '\u12c0' ..'\u12c2' - | '\u12c3' ..'\u12c5' - | '\u12c8' ..'\u12d6' - | '\u12d8' ..'\u1310' - | '\u1312' ..'\u1315' - | '\u1318' ..'\u135a' - | '\u1380' ..'\u138f' - | '\u13a0' ..'\u13f4' - | '\u1401' ..'\u166c' - | '\u166f' ..'\u167f' - | '\u1681' ..'\u169a' - | '\u16a0' ..'\u16ea' - | '\u16f1' ..'\u16f8' - | '\u1700' ..'\u170c' - | '\u170e' ..'\u1711' - | '\u1720' ..'\u1731' - | '\u1740' ..'\u1751' - | '\u1760' ..'\u176c' - | '\u176e' ..'\u1770' - | '\u1780' ..'\u17b3' - | '\u17dc' ..'\u1820' - | '\u1821' ..'\u1842' - | '\u1844' ..'\u1877' - | '\u1880' ..'\u18a8' - | '\u18aa' ..'\u18b0' - | '\u18b1' ..'\u18f5' - | '\u1900' ..'\u191e' - | '\u1950' ..'\u196d' - | '\u1970' ..'\u1974' - | '\u1980' ..'\u19ab' - | '\u19c1' ..'\u19c7' - | '\u1a00' ..'\u1a16' - | '\u1a20' ..'\u1a54' - | '\u1b05' ..'\u1b33' - | '\u1b45' ..'\u1b4b' - | '\u1b83' ..'\u1ba0' - | '\u1bae' ..'\u1baf' - | '\u1bba' ..'\u1be5' - | '\u1c00' ..'\u1c23' - | '\u1c4d' ..'\u1c4f' - | '\u1c5a' ..'\u1c77' - | '\u1ce9' ..'\u1cec' - | '\u1cee' ..'\u1cf1' - | '\u1cf5' ..'\u1cf6' - | '\u2135' ..'\u2138' - | '\u2d30' ..'\u2d67' - | '\u2d80' ..'\u2d96' - | '\u2da0' ..'\u2da6' - | '\u2da8' ..'\u2dae' - | '\u2db0' ..'\u2db6' - | '\u2db8' ..'\u2dbe' - | '\u2dc0' ..'\u2dc6' - | '\u2dc8' ..'\u2dce' - | '\u2dd0' ..'\u2dd6' - | '\u2dd8' ..'\u2dde' - | '\u3006' ..'\u303c' - | '\u3041' ..'\u3096' - | '\u309f' ..'\u30a1' - | '\u30a2' ..'\u30fa' - | '\u30ff' ..'\u3105' - | '\u3106' ..'\u312d' - | '\u3131' ..'\u318e' - | '\u31a0' ..'\u31ba' - | '\u31f0' ..'\u31ff' - | '\u3400' ..'\u4db5' - | '\u4e00' ..'\u9fcc' - | '\ua000' ..'\ua014' - | '\ua016' ..'\ua48c' - | '\ua4d0' ..'\ua4f7' - | '\ua500' ..'\ua60b' - | '\ua610' ..'\ua61f' - | '\ua62a' ..'\ua62b' - | '\ua66e' ..'\ua6a0' - | '\ua6a1' ..'\ua6e5' - | '\ua7f7' ..'\ua7fb' - | '\ua7fc' ..'\ua801' - | '\ua803' ..'\ua805' - | '\ua807' ..'\ua80a' - | '\ua80c' ..'\ua822' - | '\ua840' ..'\ua873' - | '\ua882' ..'\ua8b3' - | '\ua8f2' ..'\ua8f7' - | '\ua8fb' ..'\ua90a' - | '\ua90b' ..'\ua925' - | '\ua930' ..'\ua946' - | '\ua960' ..'\ua97c' - | '\ua984' ..'\ua9b2' - | '\ua9e0' ..'\ua9e4' - | '\ua9e7' ..'\ua9ef' - | '\ua9fa' ..'\ua9fe' - | '\uaa00' ..'\uaa28' - | '\uaa40' ..'\uaa42' - | '\uaa44' ..'\uaa4b' - | '\uaa60' ..'\uaa6f' - | '\uaa71' ..'\uaa76' - | '\uaa7a' ..'\uaa7e' - | '\uaa7f' ..'\uaaaf' - | '\uaab1' ..'\uaab5' - | '\uaab6' ..'\uaab9' - | '\uaaba' ..'\uaabd' - | '\uaac0' ..'\uaac2' - | '\uaadb' ..'\uaadc' - | '\uaae0' ..'\uaaea' - | '\uaaf2' ..'\uab01' - | '\uab02' ..'\uab06' - | '\uab09' ..'\uab0e' - | '\uab11' ..'\uab16' - | '\uab20' ..'\uab26' - | '\uab28' ..'\uab2e' - | '\uabc0' ..'\uabe2' - | '\uac00' ..'\ud7a3' - | '\ud7b0' ..'\ud7c6' - | '\ud7cb' ..'\ud7fb' - | '\uf900' ..'\ufa6d' - | '\ufa70' ..'\ufad9' - | '\ufb1d' ..'\ufb1f' - | '\ufb20' ..'\ufb28' - | '\ufb2a' ..'\ufb36' - | '\ufb38' ..'\ufb3c' - | '\ufb3e' ..'\ufb40' - | '\ufb41' ..'\ufb43' - | '\ufb44' ..'\ufb46' - | '\ufb47' ..'\ufbb1' - | '\ufbd3' ..'\ufd3d' - | '\ufd50' ..'\ufd8f' - | '\ufd92' ..'\ufdc7' - | '\ufdf0' ..'\ufdfb' - | '\ufe70' ..'\ufe74' - | '\ufe76' ..'\ufefc' - | '\uff66' ..'\uff6f' - | '\uff71' ..'\uff9d' - | '\uffa0' ..'\uffbe' - | '\uffc2' ..'\uffc7' - | '\uffca' ..'\uffcf' - | '\uffd2' ..'\uffd7' - | '\uffda' ..'\uffdc' -; - -fragment UnicodeClassNL: - '\u16EE' // RUNIC ARLAUG SYMBOL - | '\u16EF' // RUNIC TVIMADUR SYMBOL - | '\u16F0' // RUNIC BELGTHOR SYMBOL - | '\u2160' // ROMAN NUMERAL ONE - | '\u2161' // ROMAN NUMERAL TWO - | '\u2162' // ROMAN NUMERAL THREE - | '\u2163' // ROMAN NUMERAL FOUR - | '\u2164' // ROMAN NUMERAL FIVE - | '\u2165' // ROMAN NUMERAL SIX - | '\u2166' // ROMAN NUMERAL SEVEN - | '\u2167' // ROMAN NUMERAL EIGHT - | '\u2168' // ROMAN NUMERAL NINE - | '\u2169' // ROMAN NUMERAL TEN - | '\u216A' // ROMAN NUMERAL ELEVEN - | '\u216B' // ROMAN NUMERAL TWELVE - | '\u216C' // ROMAN NUMERAL FIFTY - | '\u216D' // ROMAN NUMERAL ONE HUNDRED - | '\u216E' // ROMAN NUMERAL FIVE HUNDRED - | '\u216F' // ROMAN NUMERAL ONE THOUSAND -; - -fragment UnicodeClassMN: - '\u0300' // COMBINING GRAVE ACCENT - | '\u0301' // COMBINING ACUTE ACCENT - | '\u0302' // COMBINING CIRCUMFLEX ACCENT - | '\u0303' // COMBINING TILDE - | '\u0304' // COMBINING MACRON - | '\u0305' // COMBINING OVERLINE - | '\u0306' // COMBINING BREVE - | '\u0307' // COMBINING DOT ABOVE - | '\u0308' // COMBINING DIAERESIS - | '\u0309' // COMBINING HOOK ABOVE - | '\u030A' // COMBINING RING ABOVE - | '\u030B' // COMBINING DOUBLE ACUTE ACCENT - | '\u030C' // COMBINING CARON - | '\u030D' // COMBINING VERTICAL LINE ABOVE - | '\u030E' // COMBINING DOUBLE VERTICAL LINE ABOVE - | '\u030F' // COMBINING DOUBLE GRAVE ACCENT - | '\u0310' // COMBINING CANDRABINDU -; - -fragment UnicodeClassMC: - '\u0903' // DEVANAGARI SIGN VISARGA - | '\u093E' // DEVANAGARI VOWEL SIGN AA - | '\u093F' // DEVANAGARI VOWEL SIGN I - | '\u0940' // DEVANAGARI VOWEL SIGN II - | '\u0949' // DEVANAGARI VOWEL SIGN CANDRA O - | '\u094A' // DEVANAGARI VOWEL SIGN SHORT O - | '\u094B' // DEVANAGARI VOWEL SIGN O - | '\u094C' // DEVANAGARI VOWEL SIGN AU -; - -fragment UnicodeClassCF: - '\u00AD' // SOFT HYPHEN - | '\u0600' // ARABIC NUMBER SIGN - | '\u0601' // ARABIC SIGN SANAH - | '\u0602' // ARABIC FOOTNOTE MARKER - | '\u0603' // ARABIC SIGN SAFHA - | '\u06DD' // ARABIC END OF AYAH -; - -fragment UnicodeClassPC: - '\u005F' // LOW LINE - | '\u203F' // UNDERTIE - | '\u2040' // CHARACTER TIE - | '\u2054' // INVERTED UNDERTIE - | '\uFE33' // PRESENTATION FORM FOR VERTICAL LOW LINE - | '\uFE34' // PRESENTATION FORM FOR VERTICAL WAVY LOW LINE - | '\uFE4D' // DASHED LOW LINE - | '\uFE4E' // CENTRELINE LOW LINE - | '\uFE4F' // WAVY LOW LINE - | '\uFF3F' // FULLWIDTH LOW LINE -; - -fragment UnicodeClassND: - '\u0030' ..'\u0039' - | '\u0660' ..'\u0669' - | '\u06f0' ..'\u06f9' - | '\u07c0' ..'\u07c9' - | '\u0966' ..'\u096f' - | '\u09e6' ..'\u09ef' - | '\u0a66' ..'\u0a6f' - | '\u0ae6' ..'\u0aef' - | '\u0b66' ..'\u0b6f' - | '\u0be6' ..'\u0bef' - | '\u0c66' ..'\u0c6f' - | '\u0ce6' ..'\u0cef' - | '\u0d66' ..'\u0d6f' - | '\u0de6' ..'\u0def' - | '\u0e50' ..'\u0e59' - | '\u0ed0' ..'\u0ed9' - | '\u0f20' ..'\u0f29' - | '\u1040' ..'\u1049' - | '\u1090' ..'\u1099' - | '\u17e0' ..'\u17e9' - | '\u1810' ..'\u1819' - | '\u1946' ..'\u194f' - | '\u19d0' ..'\u19d9' - | '\u1a80' ..'\u1a89' - | '\u1a90' ..'\u1a99' - | '\u1b50' ..'\u1b59' - | '\u1bb0' ..'\u1bb9' - | '\u1c40' ..'\u1c49' - | '\u1c50' ..'\u1c59' - | '\ua620' ..'\ua629' - | '\ua8d0' ..'\ua8d9' - | '\ua900' ..'\ua909' - | '\ua9d0' ..'\ua9d9' - | '\ua9f0' ..'\ua9f9' - | '\uaa50' ..'\uaa59' - | '\uabf0' ..'\uabf9' - | '\uff10' ..'\uff19' -; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpParser.g4 deleted file mode 100644 index 6ce8e651..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpParser.g4 +++ /dev/null @@ -1,1325 +0,0 @@ -// Eclipse Public License - v 1.0, http://www.eclipse.org/legal/epl-v10.html -// Copyright (c) 2013, Christian Wulf (chwchw@gmx.de) -// Copyright (c) 2016-2017, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies. - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar CSharpParser; - -options { - tokenVocab = CSharpLexer; - superClass = CSharpParserBase; -} - -// entry point -compilation_unit - : BYTE_ORDER_MARK? extern_alias_directives? using_directives? global_attribute_section* namespace_member_declarations? EOF - ; - -//B.2 Syntactic grammar - -//B.2.1 Basic concepts - -namespace_or_type_name - : (identifier type_argument_list? | qualified_alias_member) ( - '.' identifier type_argument_list? - )* - ; - -//B.2.2 Types -type_ - : base_type ('?' | rank_specifier | '*')* - ; - -base_type - : simple_type - | class_type // represents types: enum, class, interface, delegate, type_parameter - | VOID '*' - | tuple_type // C# 7.0 - ; - -// C# 7.0 tuple types -tuple_type - : '(' tuple_element (',' tuple_element)+ ')' - ; - -tuple_element - : type_ identifier? - ; - -simple_type - : numeric_type - | BOOL - ; - -numeric_type - : integral_type - | floating_point_type - | DECIMAL - ; - -integral_type - : SBYTE - | BYTE - | SHORT - | USHORT - | INT - | UINT - | LONG - | ULONG - | CHAR - ; - -floating_point_type - : FLOAT - | DOUBLE - ; - -/** namespace_or_type_name, OBJECT, STRING */ -class_type - : namespace_or_type_name - | OBJECT - | DYNAMIC - | STRING - ; - -type_argument_list - : '<' type_ (',' type_)* '>' - ; - -//B.2.4 Expressions -argument_list - : argument (',' argument)* - ; - -argument - : (identifier ':')? refout = (REF | OUT | IN)? (expression | (VAR | type_) expression) // C# 7.2: IN - ; - -expression - : assignment - | non_assignment_expression - | REF non_assignment_expression // C# 7.0: ref expression (ref locals, ref return) - ; - -non_assignment_expression - : lambda_expression - | query_expression - | conditional_expression - ; - -assignment - : unary_expression assignment_operator expression - | unary_expression '??=' throwable_expression // C# 8.0: null-coalescing assignment - ; - -assignment_operator - : '=' - | '+=' - | '-=' - | '*=' - | '/=' - | '%=' - | '&=' - | '|=' - | '^=' - | '<<=' - | right_shift_assignment - ; - -conditional_expression - : null_coalescing_expression ('?' throwable_expression ':' throwable_expression)? - ; - -null_coalescing_expression - : conditional_or_expression ('??' (null_coalescing_expression | throw_expression))? // C# 7.0: throw_expression in ?? - ; - -conditional_or_expression - : conditional_and_expression (OP_OR conditional_and_expression)* - ; - -conditional_and_expression - : inclusive_or_expression (OP_AND inclusive_or_expression)* - ; - -inclusive_or_expression - : exclusive_or_expression ('|' exclusive_or_expression)* - ; - -exclusive_or_expression - : and_expression ('^' and_expression)* - ; - -and_expression - : equality_expression ('&' equality_expression)* - ; - -equality_expression - : relational_expression ((OP_EQ | OP_NE) relational_expression)* - ; - -relational_expression - : shift_expression (('<' | '>' | '<=' | '>=') shift_expression | IS isType // C# 7.0: type pattern matching - | AS type_)* - ; - -shift_expression - : additive_expression (('<<' | right_shift) additive_expression)* - ; - -additive_expression - : multiplicative_expression (('+' | '-') multiplicative_expression)* - ; - -multiplicative_expression - : switch_expression (('*' | '/' | '%') switch_expression)* - ; - -// C# 8.0 switch expression -switch_expression - : range_expression ('switch' '{' (switch_expression_arms ','?)? '}')? - ; - -// C# 8.0 -switch_expression_arms - : switch_expression_arm (',' switch_expression_arm)* - ; - -// C# 8.0 -switch_expression_arm - : expression case_guard? right_arrow throwable_expression - ; - -// C# 8.0 range expression -range_expression - : unary_expression - | unary_expression? OP_RANGE unary_expression? // C# 8.0 - ; - -// https://msdn.microsoft.com/library/6a71f45d(v=vs.110).aspx -unary_expression - : cast_expression - | primary_expression - | '+' unary_expression - | '-' unary_expression - | BANG unary_expression - | '~' unary_expression - | '++' unary_expression - | '--' unary_expression - | AWAIT unary_expression // C# 5 - | '&' unary_expression - | '*' unary_expression - | '^' unary_expression // C# 8 ranges - ; - -cast_expression - : OPEN_PARENS type_ CLOSE_PARENS unary_expression - ; - -primary_expression // Null-conditional operators C# 6: https://msdn.microsoft.com/en-us/library/dn986595.aspx - : pe = primary_expression_start '!'? bracket_expression* '!'? ( - (member_access | method_invocation | '++' | '--' | '->' identifier) '!'? bracket_expression* '!'? - )* - ; - -primary_expression_start - : literal # literalExpression - | identifier type_argument_list? # simpleNameExpression - | OPEN_PARENS expression CLOSE_PARENS # parenthesisExpressions - | predefined_type # memberAccessExpression - | qualified_alias_member # memberAccessExpression - | LITERAL_ACCESS # literalAccessExpression - | THIS # thisReferenceExpression - | BASE ('.' identifier type_argument_list? | '[' expression_list ']') # baseAccessExpression - | NEW ( - type_ ( - object_creation_expression - | object_or_collection_initializer - | '[' expression_list ']' rank_specifier* array_initializer? - | rank_specifier+ array_initializer - ) - | anonymous_object_initializer - | rank_specifier array_initializer - ) # objectCreationExpression - | OPEN_PARENS argument ( ',' argument)+ CLOSE_PARENS # tupleExpression // C# 7.0 - | TYPEOF OPEN_PARENS (unbound_type_name | type_ | VOID) CLOSE_PARENS # typeofExpression - | CHECKED OPEN_PARENS expression CLOSE_PARENS # checkedExpression - | UNCHECKED OPEN_PARENS expression CLOSE_PARENS # uncheckedExpression - | DEFAULT (OPEN_PARENS type_ CLOSE_PARENS)? # defaultValueExpression // C# 7.1: default literal (parens optional) - | ASYNC? DELEGATE (OPEN_PARENS explicit_anonymous_function_parameter_list? CLOSE_PARENS)? block # anonymousMethodExpression - | SIZEOF OPEN_PARENS type_ CLOSE_PARENS # sizeofExpression - // C# 6: https://msdn.microsoft.com/en-us/library/dn986596.aspx - | NAMEOF OPEN_PARENS (identifier '.')* identifier CLOSE_PARENS # nameofExpression - ; - -// C# 7.0 throw expression -throwable_expression - : expression - | throw_expression - ; - -// C# 7.0 -throw_expression - : THROW expression - ; - -member_access - : '?'? '.' identifier type_argument_list? - ; - -bracket_expression - : '?'? '[' indexer_argument (',' indexer_argument)* ']' - ; - -indexer_argument - : (identifier ':')? expression - ; - -predefined_type - : BOOL - | BYTE - | CHAR - | DECIMAL - | DOUBLE - | FLOAT - | INT - | LONG - | OBJECT - | SBYTE - | SHORT - | STRING - | UINT - | ULONG - | USHORT - ; - -expression_list - : expression (',' expression)* - ; - -object_or_collection_initializer - : object_initializer - | collection_initializer - ; - -object_initializer - : OPEN_BRACE (member_initializer_list ','?)? CLOSE_BRACE - ; - -member_initializer_list - : member_initializer (',' member_initializer)* - ; - -member_initializer - : (identifier | '[' expression ']') '=' initializer_value // C# 6 - ; - -initializer_value - : expression - | object_or_collection_initializer - ; - -collection_initializer - : OPEN_BRACE element_initializer (',' element_initializer)* ','? CLOSE_BRACE - ; - -element_initializer - : non_assignment_expression - | OPEN_BRACE expression_list CLOSE_BRACE - ; - -anonymous_object_initializer - : OPEN_BRACE (member_declarator_list ','?)? CLOSE_BRACE - ; - -member_declarator_list - : member_declarator (',' member_declarator)* - ; - -member_declarator - : primary_expression - | identifier '=' expression - ; - -unbound_type_name - : identifier (generic_dimension_specifier? | '::' identifier generic_dimension_specifier?) ( - '.' identifier generic_dimension_specifier? - )* - ; - -generic_dimension_specifier - : '<' ','* '>' - ; - -// C# 7.0: IS type pattern (identifier? = optional binding variable) -isType - : base_type (rank_specifier | '*')* '?'? isTypePatternArms? identifier? - ; - -// C# 8.0: property pattern arms (extended from isType) -isTypePatternArms - : '{' isTypePatternArm (',' isTypePatternArm)* '}' - ; - -// C# 8.0 -isTypePatternArm - : identifier ':' expression - ; - -lambda_expression - : ASYNC? anonymous_function_signature right_arrow anonymous_function_body - ; - -anonymous_function_signature - : OPEN_PARENS CLOSE_PARENS - | OPEN_PARENS explicit_anonymous_function_parameter_list CLOSE_PARENS - | OPEN_PARENS implicit_anonymous_function_parameter_list CLOSE_PARENS - | identifier - ; - -explicit_anonymous_function_parameter_list - : explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)* - ; - -explicit_anonymous_function_parameter - : refout = (REF | OUT | IN)? type_ identifier // C# 7.2: IN - ; - -implicit_anonymous_function_parameter_list - : identifier (',' identifier)* - ; - -anonymous_function_body - : throwable_expression - | block - ; - -query_expression - : from_clause query_body - ; - -from_clause - : FROM type_? identifier IN expression - ; - -query_body - : query_body_clause* select_or_group_clause query_continuation? - ; - -query_body_clause - : from_clause - | let_clause - | where_clause - | combined_join_clause - | orderby_clause - ; - -let_clause - : LET identifier '=' expression - ; - -where_clause - : WHERE expression - ; - -combined_join_clause - : JOIN type_? identifier IN expression ON expression EQUALS expression (INTO identifier)? - ; - -orderby_clause - : ORDERBY ordering (',' ordering)* - ; - -ordering - : expression dir = (ASCENDING | DESCENDING)? - ; - -select_or_group_clause - : SELECT expression - | GROUP expression BY expression - ; - -query_continuation - : INTO identifier query_body - ; - -//B.2.5 Statements -statement - : labeled_Statement - | declarationStatement - | embedded_statement - ; - -declarationStatement - : local_variable_declaration ';' - | local_constant_declaration ';' - | local_function_declaration // C# 7.0 - ; - -// C# 7.0 local functions -local_function_declaration - : local_function_header local_function_body - ; - -// C# 7.0 -local_function_header - : local_function_modifiers? return_type identifier type_parameter_list? OPEN_PARENS formal_parameter_list? CLOSE_PARENS - type_parameter_constraints_clauses? - ; - -// C# 7.0; STATIC modifier: C# 8.0 (static local functions) -local_function_modifiers - : (ASYNC | UNSAFE) STATIC? // C# 8.0: STATIC - | STATIC (ASYNC | UNSAFE) // C# 8.0: STATIC - ; - -// C# 7.0 -local_function_body - : block - | right_arrow throwable_expression ';' - ; - -labeled_Statement - : identifier ':' statement - ; - -embedded_statement - : block - | simple_embedded_statement - ; - -simple_embedded_statement - : ';' # theEmptyStatement - | expression ';' # expressionStatement - - // selection statements - | IF OPEN_PARENS expression CLOSE_PARENS if_body (ELSE if_body)? # ifStatement - | SWITCH OPEN_PARENS expression CLOSE_PARENS OPEN_BRACE switch_section* CLOSE_BRACE # switchStatement - - // iteration statements - | WHILE OPEN_PARENS expression CLOSE_PARENS embedded_statement # whileStatement - | DO embedded_statement WHILE OPEN_PARENS expression CLOSE_PARENS ';' # doStatement - | FOR OPEN_PARENS for_initializer? ';' expression? ';' for_iterator? CLOSE_PARENS embedded_statement # forStatement - | AWAIT? FOREACH OPEN_PARENS local_variable_type identifier IN expression CLOSE_PARENS embedded_statement # foreachStatement // C# 8.0: AWAIT? - - // jump statements - | BREAK ';' # breakStatement - | CONTINUE ';' # continueStatement - | GOTO (identifier | CASE expression | DEFAULT) ';' # gotoStatement - | RETURN expression? ';' # returnStatement - | THROW expression? ';' # throwStatement - | TRY block (catch_clauses finally_clause? | finally_clause) # tryStatement - | CHECKED block # checkedStatement - | UNCHECKED block # uncheckedStatement - | LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement # lockStatement - | USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement # usingStatement - | YIELD (RETURN expression | BREAK) ';' # yieldStatement - - // unsafe statements - | UNSAFE block # unsafeStatement - | FIXED OPEN_PARENS pointer_type fixed_pointer_declarators CLOSE_PARENS embedded_statement # fixedStatement - ; - -block - : OPEN_BRACE statement_list? CLOSE_BRACE - ; - -local_variable_declaration - : (USING | REF | REF READONLY)? local_variable_type local_variable_declarator ( // C# 8.0: USING; C# 7.0: REF, REF READONLY - ',' local_variable_declarator { this.IsLocalVariableDeclaration() }? - )* - | FIXED pointer_type fixed_pointer_declarators - ; - -local_variable_type - : VAR - | type_ - ; - -local_variable_declarator - : identifier ('=' REF? local_variable_initializer)? // C# 7.0: REF? (ref local assignment) - ; - -local_variable_initializer - : expression - | array_initializer - | stackalloc_initializer // C# 7.0 - ; - -local_constant_declaration - : CONST type_ constant_declarators - ; - -if_body - : block - | simple_embedded_statement - ; - -switch_section - : switch_label+ statement_list - ; - -switch_label - : CASE expression case_guard? ':' // C# 7.0: arbitrary expression (not just constant) + case_guard - | DEFAULT ':' - ; - -// C# 7.0 case guard (when clause in switch) -case_guard - : WHEN expression - ; - -statement_list - : statement+ - ; - -for_initializer - : local_variable_declaration - | expression (',' expression)* - ; - -for_iterator - : expression (',' expression)* - ; - -catch_clauses - : specific_catch_clause specific_catch_clause* general_catch_clause? - | general_catch_clause - ; - -specific_catch_clause - : CATCH OPEN_PARENS class_type identifier? CLOSE_PARENS exception_filter? block - ; - -general_catch_clause - : CATCH exception_filter? block - ; - -exception_filter // C# 6 - : WHEN OPEN_PARENS expression CLOSE_PARENS - ; - -finally_clause - : FINALLY block - ; - -resource_acquisition - : local_variable_declaration - | expression - ; - -//B.2.6 Namespaces; -namespace_declaration - : NAMESPACE qi = qualified_identifier namespace_body ';'? - ; - -qualified_identifier - : identifier ('.' identifier)* - ; - -namespace_body - : OPEN_BRACE extern_alias_directives? using_directives? namespace_member_declarations? CLOSE_BRACE - ; - -extern_alias_directives - : extern_alias_directive+ - ; - -extern_alias_directive - : EXTERN ALIAS identifier ';' - ; - -using_directives - : using_directive+ - ; - -using_directive - : USING identifier '=' namespace_or_type_name ';' # usingAliasDirective - | USING namespace_or_type_name ';' # usingNamespaceDirective - // C# 6: https://msdn.microsoft.com/en-us/library/ms228593.aspx - | USING STATIC namespace_or_type_name ';' # usingStaticDirective - ; - -namespace_member_declarations - : namespace_member_declaration+ - ; - -namespace_member_declaration - : namespace_declaration - | type_declaration - ; - -type_declaration - : attributes? all_member_modifiers? ( - class_definition - | struct_definition - | interface_definition - | enum_definition - | delegate_definition - ) - ; - -qualified_alias_member - : identifier '::' identifier type_argument_list? - ; - -//B.2.7 Classes; -type_parameter_list - : '<' type_parameter (',' type_parameter)* '>' - ; - -type_parameter - : attributes? identifier - ; - -class_base - : ':' class_type (',' namespace_or_type_name)* - ; - -interface_type_list - : namespace_or_type_name (',' namespace_or_type_name)* - ; - -type_parameter_constraints_clauses - : type_parameter_constraints_clause+ - ; - -type_parameter_constraints_clause - : WHERE identifier ':' type_parameter_constraints - ; - -type_parameter_constraints - : constructor_constraint - | primary_constraint (',' secondary_constraints)? (',' constructor_constraint)? - ; - -primary_constraint - : class_type - | CLASS '?'? - | STRUCT - | UNMANAGED // C# 7.2: unmanaged type constraint - ; - -// namespace_or_type_name includes identifier -secondary_constraints - : namespace_or_type_name (',' namespace_or_type_name)* - ; - -constructor_constraint - : NEW OPEN_PARENS CLOSE_PARENS - ; - -class_body - : OPEN_BRACE class_member_declarations? CLOSE_BRACE - ; - -class_member_declarations - : class_member_declaration+ - ; - -class_member_declaration - : attributes? all_member_modifiers? (common_member_declaration | destructor_definition) - ; - -all_member_modifiers - : all_member_modifier+ - ; - -all_member_modifier - : NEW - | PUBLIC - | PROTECTED - | INTERNAL - | PRIVATE - | READONLY - | VOLATILE - | VIRTUAL - | SEALED - | OVERRIDE - | ABSTRACT - | STATIC - | UNSAFE - | EXTERN - | PARTIAL - | ASYNC // C# 5 - ; - -// represents the intersection of struct_member_declaration and class_member_declaration -common_member_declaration - : constant_declaration - | typed_member_declaration - | event_declaration - | conversion_operator_declarator (body | right_arrow throwable_expression ';') // C# 6 - | constructor_declaration - | VOID method_declaration - | class_definition - | struct_definition - | interface_definition - | enum_definition - | delegate_definition - ; - -typed_member_declaration - : (REF | READONLY REF | REF READONLY)? type_ ( // C# 7.0: REF/READONLY REF/REF READONLY (ref return types) - namespace_or_type_name '.' indexer_declaration - | method_declaration - | property_declaration - | indexer_declaration - | operator_declaration - | field_declaration - ) - ; - -constant_declarators - : constant_declarator (',' constant_declarator)* - ; - -constant_declarator - : identifier '=' expression - ; - -variable_declarators - : variable_declarator (',' variable_declarator)* - ; - -variable_declarator - : identifier ('=' variable_initializer)? - ; - -variable_initializer - : expression - | array_initializer - ; - -return_type - : type_ - | VOID - ; - -member_name - : namespace_or_type_name - ; - -method_body - : block - | ';' - ; - -formal_parameter_list - : parameter_array - | fixed_parameters (',' parameter_array)? - ; - -fixed_parameters - : fixed_parameter (',' fixed_parameter)* - ; - -fixed_parameter - : attributes? parameter_modifier? arg_declaration - | ARGLIST - ; - -parameter_modifier - : REF - | OUT - | IN // C# 7.2: in parameter modifier - | REF THIS // C# 7.2: ref extension method receiver - | IN THIS // C# 7.2: in extension method receiver - | THIS - ; - -parameter_array - : attributes? PARAMS array_type identifier - ; - -accessor_declarations - : attrs = attributes? mods = accessor_modifier? ( - GET accessor_body set_accessor_declaration? - | SET accessor_body get_accessor_declaration? - ) - ; - -get_accessor_declaration - : attributes? accessor_modifier? GET accessor_body - ; - -set_accessor_declaration - : attributes? accessor_modifier? SET accessor_body - ; - -accessor_modifier - : PROTECTED - | INTERNAL - | PRIVATE - | PROTECTED INTERNAL - | INTERNAL PROTECTED - ; - -accessor_body - : block - | ';' - ; - -event_accessor_declarations - : attributes? (ADD block remove_accessor_declaration | REMOVE block add_accessor_declaration) - ; - -add_accessor_declaration - : attributes? ADD block - ; - -remove_accessor_declaration - : attributes? REMOVE block - ; - -overloadable_operator - : '+' - | '-' - | BANG - | '~' - | '++' - | '--' - | TRUE - | FALSE - | '*' - | '/' - | '%' - | '&' - | '|' - | '^' - | '<<' - | right_shift - | OP_EQ - | OP_NE - | '>' - | '<' - | '>=' - | '<=' - ; - -conversion_operator_declarator - : (IMPLICIT | EXPLICIT) OPERATOR type_ OPEN_PARENS arg_declaration CLOSE_PARENS - ; - -constructor_initializer - : ':' (BASE | THIS) OPEN_PARENS argument_list? CLOSE_PARENS - ; - -body - : block - | ';' - ; - -//B.2.8 Structs -struct_interfaces - : ':' interface_type_list - ; - -struct_body - : OPEN_BRACE struct_member_declaration* CLOSE_BRACE - ; - -struct_member_declaration - : attributes? all_member_modifiers? ( - common_member_declaration - | FIXED type_ fixed_size_buffer_declarator+ ';' - ) - ; - -//B.2.9 Arrays -array_type - : base_type (('*' | '?')* rank_specifier)+ - ; - -rank_specifier - : '[' ','* ']' - ; - -array_initializer - : OPEN_BRACE (variable_initializer (',' variable_initializer)* ','?)? CLOSE_BRACE - ; - -//B.2.10 Interfaces -variant_type_parameter_list - : '<' variant_type_parameter (',' variant_type_parameter)* '>' - ; - -variant_type_parameter - : attributes? variance_annotation? identifier - ; - -variance_annotation - : IN - | OUT - ; - -interface_base - : ':' interface_type_list - ; - -interface_body // ignored in csharp 8 - : OPEN_BRACE interface_member_declaration* CLOSE_BRACE - ; - -interface_member_declaration - : attributes? NEW? ( - UNSAFE? (REF | REF READONLY | READONLY REF)? type_ ( // C# 7.0: ref return types in interface - identifier type_parameter_list? OPEN_PARENS formal_parameter_list? CLOSE_PARENS type_parameter_constraints_clauses? ';' - | identifier OPEN_BRACE interface_accessors CLOSE_BRACE - | THIS '[' formal_parameter_list ']' OPEN_BRACE interface_accessors CLOSE_BRACE - ) - | UNSAFE? VOID identifier type_parameter_list? OPEN_PARENS formal_parameter_list? CLOSE_PARENS type_parameter_constraints_clauses? ';' - | EVENT type_ identifier ';' - ) - ; - -interface_accessors - : attributes? (GET ';' (attributes? SET ';')? | SET ';' (attributes? GET ';')?) - ; - -//B.2.11 Enums -enum_base - : ':' type_ - ; - -enum_body - : OPEN_BRACE (enum_member_declaration (',' enum_member_declaration)* ','?)? CLOSE_BRACE - ; - -enum_member_declaration - : attributes? identifier ('=' expression)? - ; - -//B.2.12 Delegates - -//B.2.13 Attributes -global_attribute_section - : '[' global_attribute_target ':' attribute_list ','? ']' - ; - -global_attribute_target - : keyword - | identifier - ; - -attributes - : attribute_section+ - ; - -attribute_section - : '[' (attribute_target ':')? attribute_list ','? ']' - ; - -attribute_target - : keyword - | identifier - ; - -attribute_list - : attribute (',' attribute)* - ; - -attribute - : namespace_or_type_name ( - OPEN_PARENS (attribute_argument (',' attribute_argument)*)? CLOSE_PARENS - )? - ; - -attribute_argument - : (identifier ':')? expression - ; - -//B.3 Grammar extensions for unsafe code -pointer_type - : (simple_type | class_type) (rank_specifier | '?')* '*' - | VOID '*' - ; - -fixed_pointer_declarators - : fixed_pointer_declarator (',' fixed_pointer_declarator)* - ; - -fixed_pointer_declarator - : identifier '=' fixed_pointer_initializer - ; - -fixed_pointer_initializer - : '&'? expression - | stackalloc_initializer - ; - -fixed_size_buffer_declarator - : identifier '[' expression ']' - ; - -stackalloc_initializer - : STACKALLOC type_ '[' expression ']' - | STACKALLOC type_? '[' expression? ']' OPEN_BRACE (expression (',' expression)* ','?)? CLOSE_BRACE // C# 7.3: stackalloc array initializer (empty list allowed) - ; - -right_arrow - : first = '=' second = '>' {$first.index + 1 == $second.index}? // Nothing between the tokens? - ; - -right_shift - : first = '>' second = '>' {$first.index + 1 == $second.index}? // Nothing between the tokens? - ; - -right_shift_assignment - : first = '>' second = '>=' {$first.index + 1 == $second.index}? // Nothing between the tokens? - ; - -literal - : boolean_literal - | string_literal - | INTEGER_LITERAL - | HEX_INTEGER_LITERAL - | BIN_INTEGER_LITERAL // C# 7.0 - | REAL_LITERAL - | CHARACTER_LITERAL - | NULL_ - ; - -boolean_literal - : TRUE - | FALSE - ; - -string_literal - : interpolated_regular_string - | interpolated_verbatium_string - | REGULAR_STRING - | VERBATIUM_STRING - ; - -interpolated_regular_string - : INTERPOLATED_REGULAR_STRING_START interpolated_regular_string_part* DOUBLE_QUOTE_INSIDE - ; - -interpolated_verbatium_string - : INTERPOLATED_VERBATIUM_STRING_START interpolated_verbatium_string_part* DOUBLE_QUOTE_INSIDE - ; - -interpolated_regular_string_part - : interpolated_string_expression - | DOUBLE_CURLY_INSIDE - | REGULAR_CHAR_INSIDE - | REGULAR_STRING_INSIDE - ; - -interpolated_verbatium_string_part - : interpolated_string_expression - | DOUBLE_CURLY_INSIDE - | VERBATIUM_DOUBLE_QUOTE_INSIDE - | VERBATIUM_INSIDE_STRING - ; - -interpolated_string_expression - : expression (',' expression)* (':' FORMAT_STRING+)? - ; - -//B.1.7 Keywords -keyword - : ABSTRACT - | AS - | BASE - | BOOL - | BREAK - | BYTE - | CASE - | CATCH - | CHAR - | CHECKED - | CLASS - | CONST - | CONTINUE - | DECIMAL - | DEFAULT - | DELEGATE - | DO - | DOUBLE - | ELSE - | ENUM - | EVENT - | EXPLICIT - | EXTERN - | FALSE - | FINALLY - | FIXED - | FLOAT - | FOR - | FOREACH - | GOTO - | IF - | IMPLICIT - | IN - | INT - | INTERFACE - | INTERNAL - | IS - | LOCK - | LONG - | NAMESPACE - | NEW - | NULL_ - | OBJECT - | OPERATOR - | OUT - | OVERRIDE - | PARAMS - | PRIVATE - | PROTECTED - | PUBLIC - | READONLY - | REF - | RETURN - | SBYTE - | SEALED - | SHORT - | SIZEOF - | STACKALLOC - | STATIC - | STRING - | STRUCT - | SWITCH - | THIS - | THROW - | TRUE - | TRY - | TYPEOF - | UINT - | ULONG - | UNCHECKED - | UNMANAGED - | UNSAFE - | USHORT - | USING - | VIRTUAL - | VOID - | VOLATILE - | WHILE - ; - -// -------------------- extra rules for modularization -------------------------------- - -class_definition - : CLASS identifier type_parameter_list? class_base? type_parameter_constraints_clauses? class_body ';'? - ; - -struct_definition - : (READONLY | REF)? STRUCT identifier type_parameter_list? struct_interfaces? type_parameter_constraints_clauses? struct_body ';'? - ; - -interface_definition - : INTERFACE identifier variant_type_parameter_list? interface_base? type_parameter_constraints_clauses? class_body ';'? - ; - -enum_definition - : ENUM identifier enum_base? enum_body ';'? - ; - -delegate_definition - : DELEGATE return_type identifier variant_type_parameter_list? OPEN_PARENS formal_parameter_list? CLOSE_PARENS type_parameter_constraints_clauses? - ';' - ; - -event_declaration - : EVENT type_ ( - variable_declarators ';' - | member_name OPEN_BRACE event_accessor_declarations CLOSE_BRACE - ) - ; - -field_declaration - : variable_declarators ';' - ; - -property_declaration // Property initializer & lambda in properties C# 6 - : member_name ( - OPEN_BRACE accessor_declarations CLOSE_BRACE ('=' variable_initializer ';')? - | right_arrow throwable_expression ';' - ) - ; - -constant_declaration - : CONST type_ constant_declarators ';' - ; - -indexer_declaration // lamdas from C# 6 - : THIS '[' formal_parameter_list ']' ( - OPEN_BRACE accessor_declarations CLOSE_BRACE - | right_arrow throwable_expression ';' - ) - ; - -destructor_definition - : '~' identifier OPEN_PARENS CLOSE_PARENS body - ; - -constructor_declaration - : identifier OPEN_PARENS formal_parameter_list? CLOSE_PARENS constructor_initializer? body - ; - -method_declaration // lamdas from C# 6 - : method_member_name type_parameter_list? OPEN_PARENS formal_parameter_list? CLOSE_PARENS type_parameter_constraints_clauses? ( - method_body - | right_arrow throwable_expression ';' - ) - ; - -method_member_name - : (identifier | identifier '::' identifier) (type_argument_list? '.' identifier)* - ; - -operator_declaration // lamdas form C# 6 - : OPERATOR overloadable_operator OPEN_PARENS IN? arg_declaration (',' IN? arg_declaration)? CLOSE_PARENS ( - body - | right_arrow throwable_expression ';' - ) - ; - -arg_declaration - : type_ identifier ('=' expression)? - ; - -method_invocation - : OPEN_PARENS argument_list? CLOSE_PARENS - ; - -object_creation_expression - : OPEN_PARENS argument_list? CLOSE_PARENS object_or_collection_initializer? - ; - -identifier - : IDENTIFIER - | ADD - | ALIAS - | ARGLIST - | ASCENDING - | ASYNC - | AWAIT - | BY - | DESCENDING - | DYNAMIC - | EQUALS - | FROM - | GET - | GROUP - | INTO - | JOIN - | LET - | NAMEOF - | ON - | ORDERBY - | PARTIAL - | REMOVE - | SELECT - | SET - | UNMANAGED - | VAR - | WHEN - | WHERE - | YIELD - ; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpPreprocessorParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpPreprocessorParser.g4 deleted file mode 100644 index 93c42f5b..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/csharp/CSharpPreprocessorParser.g4 +++ /dev/null @@ -1,48 +0,0 @@ -// Eclipse Public License - v 1.0, http://www.eclipse.org/legal/epl-v10.html -// Copyright (c) 2013, Christian Wulf (chwchw@gmx.de) -// Copyright (c) 2016-2017, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies. - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar CSharpPreprocessorParser; - -options { - tokenVocab = CSharpLexer; - superClass = CSharpPreprocessorParserBase; -} - -preprocessor_directive - returns[Boolean value] - : DEFINE CONDITIONAL_SYMBOL directive_new_line_or_sharp { this.OnPreprocessorDirectiveDefine(); } # preprocessorDeclaration - | UNDEF CONDITIONAL_SYMBOL directive_new_line_or_sharp { this.OnPreprocessorDirectiveUndef(); } # preprocessorDeclaration - | IF expr = preprocessor_expression directive_new_line_or_sharp { this.OnPreprocessorDirectiveIf(); } # preprocessorConditional - | ELIF expr = preprocessor_expression directive_new_line_or_sharp { this.OnPreprocessorDirectiveElif(); } # preprocessorConditional - | ELSE directive_new_line_or_sharp { this.OnPreprocessorDirectiveElse(); } # preprocessorConditional - | ENDIF directive_new_line_or_sharp { this.OnPreprocessorDirectiveEndif(); } # preprocessorConditional - | LINE (DIGITS STRING? | DEFAULT | DIRECTIVE_HIDDEN) directive_new_line_or_sharp { this.OnPreprocessorDirectiveLine(); } # preprocessorLine - | ERROR TEXT directive_new_line_or_sharp { this.OnPreprocessorDirectiveError(); } # preprocessorDiagnostic - | WARNING TEXT directive_new_line_or_sharp { this.OnPreprocessorDirectiveWarning(); } # preprocessorDiagnostic - | REGION TEXT? directive_new_line_or_sharp { this.OnPreprocessorDirectiveRegion(); } # preprocessorRegion - | ENDREGION TEXT? directive_new_line_or_sharp { this.OnPreprocessorDirectiveEndregion(); } # preprocessorRegion - | PRAGMA TEXT directive_new_line_or_sharp { this.OnPreprocessorDirectivePragma(); } # preprocessorPragma - | NULLABLE TEXT directive_new_line_or_sharp { this.OnPreprocessorDirectiveNullable(); } # preprocessorNullable // C# 8.0 - ; - -directive_new_line_or_sharp - : DIRECTIVE_NEW_LINE - | EOF - ; - -preprocessor_expression - returns[String value] - : TRUE { this.OnPreprocessorExpressionTrue(); } - | FALSE { this.OnPreprocessorExpressionFalse(); } - | CONDITIONAL_SYMBOL { this.OnPreprocessorExpressionConditionalSymbol(); } - | OPEN_PARENS expr = preprocessor_expression CLOSE_PARENS { this.OnPreprocessorExpressionConditionalOpenParens(); } - | BANG expr = preprocessor_expression { this.OnPreprocessorExpressionConditionalBang(); } - | expr1 = preprocessor_expression OP_EQ expr2 = preprocessor_expression { this.OnPreprocessorExpressionConditionalEq(); } - | expr1 = preprocessor_expression OP_NE expr2 = preprocessor_expression { this.OnPreprocessorExpressionConditionalNe(); } - | expr1 = preprocessor_expression OP_AND expr2 = preprocessor_expression { this.OnPreprocessorExpressionConditionalAnd(); } - | expr1 = preprocessor_expression OP_OR expr2 = preprocessor_expression { this.OnPreprocessorExpressionConditionalOr(); } - ; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoLexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoLexer.g4 deleted file mode 100644 index fac66736..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoLexer.g4 +++ /dev/null @@ -1,223 +0,0 @@ -/* - [The "BSD licence"] - Copyright (c) 2017 Sasa Coh, Michał Błotniak - Copyright (c) 2019 Ivan Kochurkin, kvanttt@gmail.com, Positive Technologies - Copyright (c) 2019 Dmitry Rassadin, flipparassa@gmail.com, Positive Technologies - Copyright (c) 2021 Martin Mirchev, mirchevmartin2203@gmail.com - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - * A Go grammar for ANTLR 4 derived from the Go Language Specification - * https://golang.org/ref/spec - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar GoLexer; - -// Keywords - -BREAK : 'break' -> mode(NLSEMI); -CASE : 'case'; -CHAN : 'chan'; -CONST : 'const'; -CONTINUE : 'continue' -> mode(NLSEMI); -DEFAULT : 'default'; -DEFER : 'defer'; -ELSE : 'else'; -FALLTHROUGH : 'fallthrough' -> mode(NLSEMI); -FOR : 'for'; -FUNC : 'func'; -GO : 'go'; -GOTO : 'goto'; -IF : 'if'; -IMPORT : 'import'; -INTERFACE : 'interface'; -MAP : 'map'; -NIL_LIT : 'nil' -> mode(NLSEMI); -PACKAGE : 'package'; -RANGE : 'range'; -RETURN : 'return' -> mode(NLSEMI); -SELECT : 'select'; -STRUCT : 'struct'; -SWITCH : 'switch'; -TYPE : 'type'; -VAR : 'var'; - -IDENTIFIER: LETTER (LETTER | UNICODE_DIGIT)* -> mode(NLSEMI); - -// Punctuation - -L_PAREN : '('; -R_PAREN : ')' -> mode(NLSEMI); -L_CURLY : '{'; -R_CURLY : '}' -> mode(NLSEMI); -L_BRACKET : '['; -R_BRACKET : ']' -> mode(NLSEMI); -ASSIGN : '='; -COMMA : ','; -SEMI : ';'; -COLON : ':'; -DOT : '.'; -PLUS_PLUS : '++' -> mode(NLSEMI); -MINUS_MINUS : '--' -> mode(NLSEMI); -DECLARE_ASSIGN : ':='; -ELLIPSIS : '...'; - -// Logical - -LOGICAL_OR : '||'; -LOGICAL_AND : '&&'; - -// Relation operators - -EQUALS : '=='; -NOT_EQUALS : '!='; -LESS : '<'; -LESS_OR_EQUALS : '<='; -GREATER : '>'; -GREATER_OR_EQUALS : '>='; - -// Arithmetic operators - -OR : '|'; -DIV : '/'; -MOD : '%'; -LSHIFT : '<<'; -RSHIFT : '>>'; -BIT_CLEAR : '&^'; -UNDERLYING : '~'; - -// Unary operators - -EXCLAMATION: '!'; - -// Mixed operators - -PLUS : '+'; -MINUS : '-'; -CARET : '^'; -STAR : '*'; -AMPERSAND : '&'; -RECEIVE : '<-'; - -// Number literals - -DECIMAL_LIT : ('0' | [1-9] ('_'? [0-9])*) -> mode(NLSEMI); -BINARY_LIT : '0' [bB] ('_'? BIN_DIGIT)+ -> mode(NLSEMI); -OCTAL_LIT : '0' [oO]? ('_'? OCTAL_DIGIT)+ -> mode(NLSEMI); -HEX_LIT : '0' [xX] ('_'? HEX_DIGIT)+ -> mode(NLSEMI); - -FLOAT_LIT: (DECIMAL_FLOAT_LIT | HEX_FLOAT_LIT) -> mode(NLSEMI); - -DECIMAL_FLOAT_LIT: DECIMALS ('.' DECIMALS? EXPONENT? | EXPONENT) | '.' DECIMALS EXPONENT?; - -HEX_FLOAT_LIT: '0' [xX] HEX_MANTISSA HEX_EXPONENT; - -fragment HEX_MANTISSA: - ('_'? HEX_DIGIT)+ ('.' ( '_'? HEX_DIGIT)*)? - | '.' HEX_DIGIT ('_'? HEX_DIGIT)* -; - -fragment HEX_EXPONENT: [pP] [+-]? DECIMALS; - -IMAGINARY_LIT: (DECIMAL_LIT | BINARY_LIT | OCTAL_LIT | HEX_LIT | FLOAT_LIT) 'i' -> mode(NLSEMI); - -// Rune literals - -fragment RUNE: '\'' (UNICODE_VALUE | BYTE_VALUE) '\''; //: '\'' (~[\n\\] | ESCAPED_VALUE) '\''; - -RUNE_LIT: RUNE -> mode(NLSEMI); - -BYTE_VALUE: OCTAL_BYTE_VALUE | HEX_BYTE_VALUE; - -OCTAL_BYTE_VALUE: '\\' OCTAL_DIGIT OCTAL_DIGIT OCTAL_DIGIT; - -HEX_BYTE_VALUE: '\\' 'x' HEX_DIGIT HEX_DIGIT; - -LITTLE_U_VALUE: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT; - -BIG_U_VALUE: - '\\' 'U' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT -; - -// String literals - -RAW_STRING_LIT : '`' ~'`'* '`' -> mode(NLSEMI); -INTERPRETED_STRING_LIT : '"' (~["\\] | ESCAPED_VALUE)* '"' -> mode(NLSEMI); - -// Hidden tokens - -WS : [ \t]+ -> channel(HIDDEN); -COMMENT : '/*' .*? '*/' -> channel(HIDDEN); -TERMINATOR : [\r\n]+ -> channel(HIDDEN); -LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN); - -fragment UNICODE_VALUE: ~[\r\n'] | LITTLE_U_VALUE | BIG_U_VALUE | ESCAPED_VALUE; - -// Fragments - -fragment ESCAPED_VALUE: - '\\' ( - 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT - | 'U' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT - | [abfnrtv\\'"] - | OCTAL_DIGIT OCTAL_DIGIT OCTAL_DIGIT - | 'x' HEX_DIGIT HEX_DIGIT - ) -; - -fragment DECIMALS: [0-9] ('_'? [0-9])*; - -fragment OCTAL_DIGIT: [0-7]; - -fragment HEX_DIGIT: [0-9a-fA-F]; - -fragment BIN_DIGIT: [01]; - -fragment EXPONENT: [eE] [+-]? DECIMALS; - -fragment LETTER: UNICODE_LETTER | '_'; - -//[\p{Nd}] matches a digit zero through nine in any script except ideographic scripts -fragment UNICODE_DIGIT: [\p{Nd}]; -//[\p{L}] matches any kind of letter from any language -fragment UNICODE_LETTER: [\p{L}]; - -mode NLSEMI; - -// Treat whitespace as normal -WS_NLSEMI: [ \t]+ -> channel(HIDDEN); -// Ignore any comments that only span one line -COMMENT_NLSEMI : '/*' ~[\r\n]*? '*/' -> channel(HIDDEN); -LINE_COMMENT_NLSEMI : '//' ~[\r\n]* -> channel(HIDDEN); -// Emit an EOS token for any newlines, semicolon, multiline comments or the EOF and -//return to normal lexing -EOS: ([\r\n]+ | ';' | '/*' .*? '*/' | EOF) -> mode(DEFAULT_MODE); -// Did not find an EOS, so go back to normal lexing -OTHER: -> mode(DEFAULT_MODE), channel(HIDDEN); \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoParser.g4 deleted file mode 100644 index 3a34beb4..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/golang/GoParser.g4 +++ /dev/null @@ -1,541 +0,0 @@ -/* - [The "BSD licence"] Copyright (c) 2017 Sasa Coh, Michał Błotniak - Copyright (c) 2019 Ivan Kochurkin, kvanttt@gmail.com, Positive Technologies - Copyright (c) 2019 Dmitry Rassadin, flipparassa@gmail.com,Positive Technologies All rights reserved. - Copyright (c) 2021 Martin Mirchev, mirchevmartin2203@gmail.com - Copyright (c) 2023 Dmitry Litovchenko, i@dlitovchenko.ru - - Redistribution and use in source and binary forms, with or without modification, are permitted - provided that the following conditions are met: 1. Redistributions of source code must retain the - above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in - binary form must reproduce the above copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided with the distribution. 3. The name - of the author may not be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * A Go grammar for ANTLR 4 derived from the Go Language Specification https://golang.org/ref/spec - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar GoParser; - -// Insert here @header. - -options { - tokenVocab = GoLexer; - superClass = GoParserBase; -} - -sourceFile - : packageClause eos (importDecl eos)* ((functionDecl | methodDecl | declaration) eos)* EOF - ; - -packageClause - : PACKAGE packageName {this.myreset();} - ; - -packageName - : identifier - ; - -identifier : IDENTIFIER ; - -importDecl - : IMPORT (importSpec | L_PAREN (importSpec eos)* R_PAREN) - ; - -importSpec - : (DOT | packageName)? importPath {this.addImportSpec();} - ; - -importPath - : string_ - ; - -declaration - : constDecl - | typeDecl - | varDecl - ; - -constDecl - : CONST (constSpec | L_PAREN (constSpec eos)* R_PAREN) - ; - -constSpec - : identifierList (type_? ASSIGN expressionList)? - ; - -identifierList - : IDENTIFIER (COMMA IDENTIFIER)* - ; - -expressionList - : expression (COMMA expression)* - ; - -typeDecl - : TYPE (typeSpec | L_PAREN (typeSpec eos)* R_PAREN) - ; - -typeSpec - : aliasDecl - | typeDef - ; - -aliasDecl - : IDENTIFIER typeParameters? ASSIGN type_ - ; - -typeDef - : IDENTIFIER typeParameters? type_ - ; - -typeParameters - : L_BRACKET typeParameterDecl (COMMA typeParameterDecl)* R_BRACKET - ; - -typeParameterDecl - : identifierList typeElement - ; - -typeElement - : typeTerm (OR typeTerm)* - ; - -typeTerm - : UNDERLYING? type_ - ; - -// Function declarations - -functionDecl - : FUNC IDENTIFIER typeParameters? signature block? - ; - -methodDecl - : FUNC receiver IDENTIFIER signature block? - ; - -receiver - : parameters - ; - -varDecl - : VAR (varSpec | L_PAREN (varSpec eos)* R_PAREN) - ; - -varSpec - : identifierList (type_ (ASSIGN expressionList)? | ASSIGN expressionList) - ; - -block - : L_CURLY statementList R_CURLY - ; - -statementList - : ( (SEMI | EOS | /* {this.closingBracket()}? */ ) statement eos)* - ; - -statement - : declaration - | labeledStmt - | simpleStmt - | goStmt - | returnStmt - | breakStmt - | continueStmt - | gotoStmt - | fallthroughStmt - | block - | ifStmt - | switchStmt - | selectStmt - | forStmt - | deferStmt - ; - -simpleStmt - : sendStmt - | incDecStmt - | assignment - | expressionStmt - | shortVarDecl - ; - -expressionStmt - : expression - ; - -sendStmt - : channel = expression RECEIVE expression - ; - -incDecStmt - : expression (PLUS_PLUS | MINUS_MINUS) - ; - -assignment - : expressionList assign_op expressionList - ; - -assign_op - : (PLUS | MINUS | OR | CARET | STAR | DIV | MOD | LSHIFT | RSHIFT | AMPERSAND | BIT_CLEAR)? ASSIGN - ; - -shortVarDecl - : identifierList DECLARE_ASSIGN expressionList - ; - -labeledStmt - : IDENTIFIER COLON statement? - ; - -returnStmt - : RETURN expressionList? - ; - -breakStmt - : BREAK IDENTIFIER? - ; - -continueStmt - : CONTINUE IDENTIFIER? - ; - -gotoStmt - : GOTO IDENTIFIER - ; - -fallthroughStmt - : FALLTHROUGH - ; - -deferStmt - : DEFER expression - ; - -ifStmt - : IF (expression | (SEMI | EOS) expression | simpleStmt (SEMI | EOS) expression) block (ELSE (ifStmt | block))? - ; - -switchStmt - : exprSwitchStmt - | typeSwitchStmt - ; - -exprSwitchStmt - : SWITCH (expression? | simpleStmt? eos expression?) L_CURLY exprCaseClause* R_CURLY - ; - -exprCaseClause - : exprSwitchCase COLON statementList - ; - -exprSwitchCase - : CASE expressionList - | DEFAULT - ; - -typeSwitchStmt - : SWITCH (typeSwitchGuard | eos typeSwitchGuard | simpleStmt eos typeSwitchGuard) L_CURLY typeCaseClause* R_CURLY - ; - -typeSwitchGuard - : (IDENTIFIER DECLARE_ASSIGN)? primaryExpr DOT L_PAREN TYPE R_PAREN - ; - -typeCaseClause - : typeSwitchCase COLON statementList - ; - -typeSwitchCase - : CASE typeList - | DEFAULT - ; - -typeList - : (type_ | NIL_LIT) (COMMA (type_ | NIL_LIT))* - ; - -selectStmt - : SELECT L_CURLY commClause* R_CURLY - ; - -commClause - : commCase COLON statementList - ; - -commCase - : CASE (sendStmt | recvStmt) - | DEFAULT - ; - -recvStmt - : (expressionList ASSIGN | identifierList DECLARE_ASSIGN)? recvExpr = expression - ; - -forStmt - : FOR (condition | forClause | rangeClause)? block - ; - -condition - : expression - ; - -forClause - : initStmt = simpleStmt? eos expression? eos postStmt = simpleStmt? - ; - -rangeClause - : (expressionList ASSIGN | identifierList DECLARE_ASSIGN)? RANGE expression - ; - -goStmt - : GO expression - ; - -type_ - : typeName typeArgs? - | typeLit - | L_PAREN type_ R_PAREN - ; - -typeArgs - : L_BRACKET typeList COMMA? R_BRACKET - ; - -typeName - : qualifiedIdent - | IDENTIFIER - ; - -typeLit - : arrayType - | structType - | pointerType - | functionType - | interfaceType - | sliceType - | mapType - | channelType - ; - -arrayType - : L_BRACKET arrayLength R_BRACKET elementType - ; - -arrayLength - : expression - ; - -elementType - : type_ - ; - -pointerType - : STAR type_ - ; - -interfaceType - : INTERFACE L_CURLY ((methodSpec | typeElement) eos)* R_CURLY - ; - -sliceType - : L_BRACKET R_BRACKET elementType - ; - -// It's possible to replace `type` with more restricted typeLit list and also pay attention to nil maps -mapType - : MAP L_BRACKET type_ R_BRACKET elementType - ; - -channelType - : ({this.isNotReceive()}? CHAN | CHAN RECEIVE | RECEIVE CHAN) elementType - ; - -methodSpec - : IDENTIFIER parameters result - | IDENTIFIER parameters - ; - -functionType - : FUNC signature - ; - -signature - : parameters result? - ; - -result - : parameters - | type_ - ; - -parameters - : L_PAREN (parameterDecl (COMMA parameterDecl)* COMMA?)? R_PAREN - ; - -parameterDecl - : identifierList? ELLIPSIS? type_ - ; - -expression - : primaryExpr - | unary_op = (PLUS | MINUS | EXCLAMATION | CARET | STAR | AMPERSAND | RECEIVE) expression - | expression mul_op = (STAR | DIV | MOD | LSHIFT | RSHIFT | AMPERSAND | BIT_CLEAR) expression - | expression add_op = (PLUS | MINUS | OR | CARET) expression - | expression rel_op = ( - EQUALS - | NOT_EQUALS - | LESS - | LESS_OR_EQUALS - | GREATER - | GREATER_OR_EQUALS - ) expression - | expression LOGICAL_AND expression - | expression LOGICAL_OR expression - ; - -primaryExpr : - ( {this.isOperand()}? operand - | {this.isConversion()}? conversion - | {this.isMethodExpr()}? methodExpr ) - ( DOT IDENTIFIER | index | slice_ | typeAssertion | arguments )* - ; - -conversion - : type_ L_PAREN expression COMMA? R_PAREN - ; - -operand - : literal - | operandName typeArgs? - | L_PAREN expression R_PAREN - ; - -literal - : basicLit - | compositeLit - | functionLit - ; - -basicLit - : NIL_LIT - | integer - | string_ - | FLOAT_LIT - ; - -integer - : DECIMAL_LIT - | BINARY_LIT - | OCTAL_LIT - | HEX_LIT - | IMAGINARY_LIT - | RUNE_LIT - ; - -operandName - : IDENTIFIER - | qualifiedIdent - ; - -qualifiedIdent - : IDENTIFIER DOT IDENTIFIER - ; - -compositeLit - : literalType literalValue - ; - -literalType - : structType - | arrayType - | L_BRACKET ELLIPSIS R_BRACKET elementType - | sliceType - | mapType - | typeName typeArgs? - ; - -literalValue - : L_CURLY (elementList COMMA?)? R_CURLY - ; - -elementList - : keyedElement (COMMA keyedElement)* - ; - -keyedElement - : (key COLON)? element - ; - -key - : expression - | literalValue - ; - -element - : expression - | literalValue - ; - -structType - : STRUCT L_CURLY (fieldDecl eos)* R_CURLY - ; - -fieldDecl - : (identifierList type_ | embeddedField) tag = string_? - ; - -string_ - : RAW_STRING_LIT - | INTERPRETED_STRING_LIT - ; - -embeddedField - : STAR? typeName typeArgs? - ; - -functionLit - : FUNC signature block - ; // function - -index - : L_BRACKET expression R_BRACKET - ; - -slice_ - : L_BRACKET (expression? COLON expression? | expression? COLON expression COLON expression) R_BRACKET - ; - -typeAssertion - : DOT L_PAREN type_ R_PAREN - ; - -arguments - : L_PAREN (({this.isTypeArgument()}? type_ (COMMA expressionList)? | {this.isExpressionArgument()}? expressionList) ELLIPSIS? COMMA?)? R_PAREN - ; - -methodExpr - : type_ DOT IDENTIFIER - ; - -eos - : SEMI - | EOS - | {this.closingBracket()}? - ; diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptLexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptLexer.g4 deleted file mode 100644 index f02948ec..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptLexer.g4 +++ /dev/null @@ -1,285 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers (original author) and Alexandre Vitorelli (contributor -> ported to CSharp) - * Copyright (c) 2017-2020 by Ivan Kochurkin (Positive Technologies): - added ECMAScript 6 support, cleared and transformed to the universal grammar. - * Copyright (c) 2018 by Juan Alvarez (contributor -> ported to Go) - * Copyright (c) 2019 by Student Main (contributor -> ES2020) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar JavaScriptLexer; - -channels { - ERROR -} - -options { - superClass = JavaScriptLexerBase; -} - -// Insert here @header for C++ lexer. - -HashBangLine : { this.IsStartOfFile()}? '#!' ~[\r\n\u2028\u2029]*; // only allowed at start -MultiLineComment : '/*' .*? '*/' -> channel(HIDDEN); -SingleLineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN); -RegularExpressionLiteral: - '/' RegularExpressionFirstChar RegularExpressionChar* {this.IsRegexPossible()}? '/' IdentifierPart* -; - -OpenBracket : '['; -CloseBracket : ']'; -OpenParen : '('; -CloseParen : ')'; -OpenBrace : '{' {this.ProcessOpenBrace();}; -TemplateCloseBrace : {this.IsInTemplateString()}? '}' // Break lines here to ensure proper transformation by Go/transformGrammar.py - {this.ProcessTemplateCloseBrace();} -> popMode; -CloseBrace : '}' {this.ProcessCloseBrace();}; -SemiColon : ';'; -Comma : ','; -Assign : '='; -QuestionMark : '?'; -QuestionMarkDot : '?.'; -Colon : ':'; -Ellipsis : '...'; -Dot : '.'; -PlusPlus : '++'; -MinusMinus : '--'; -Plus : '+'; -Minus : '-'; -BitNot : '~'; -Not : '!'; -Multiply : '*'; -Divide : '/'; -Modulus : '%'; -Power : '**'; -NullCoalesce : '??'; -Hashtag : '#'; -RightShiftArithmetic : '>>'; -LeftShiftArithmetic : '<<'; -RightShiftLogical : '>>>'; -LessThan : '<'; -MoreThan : '>'; -LessThanEquals : '<='; -GreaterThanEquals : '>='; -Equals_ : '=='; -NotEquals : '!='; -IdentityEquals : '==='; -IdentityNotEquals : '!=='; -BitAnd : '&'; -BitXOr : '^'; -BitOr : '|'; -And : '&&'; -Or : '||'; -MultiplyAssign : '*='; -DivideAssign : '/='; -ModulusAssign : '%='; -PlusAssign : '+='; -MinusAssign : '-='; -LeftShiftArithmeticAssign : '<<='; -RightShiftArithmeticAssign : '>>='; -RightShiftLogicalAssign : '>>>='; -BitAndAssign : '&='; -BitXorAssign : '^='; -BitOrAssign : '|='; -PowerAssign : '**='; -NullishCoalescingAssign : '??='; -ARROW : '=>'; - -/// Null Literals - -NullLiteral: 'null'; - -/// Boolean Literals - -BooleanLiteral: 'true' | 'false'; - -/// Numeric Literals - -DecimalLiteral: - DecimalIntegerLiteral '.' [0-9] [0-9_]* ExponentPart? - | '.' [0-9] [0-9_]* ExponentPart? - | DecimalIntegerLiteral ExponentPart? -; - -/// Numeric Literals - -HexIntegerLiteral : '0' [xX] [0-9a-fA-F] HexDigit*; -OctalIntegerLiteral : '0' [0-7]+ {!this.IsStrictMode()}?; -OctalIntegerLiteral2 : '0' [oO] [0-7] [_0-7]*; -BinaryIntegerLiteral : '0' [bB] [01] [_01]*; - -BigHexIntegerLiteral : '0' [xX] [0-9a-fA-F] HexDigit* 'n'; -BigOctalIntegerLiteral : '0' [oO] [0-7] [_0-7]* 'n'; -BigBinaryIntegerLiteral : '0' [bB] [01] [_01]* 'n'; -BigDecimalIntegerLiteral : DecimalIntegerLiteral 'n'; - -/// Keywords - -Break : 'break'; -Do : 'do'; -Instanceof : 'instanceof'; -Typeof : 'typeof'; -Case : 'case'; -Else : 'else'; -New : 'new'; -Var : 'var'; -Catch : 'catch'; -Finally : 'finally'; -Return : 'return'; -Void : 'void'; -Continue : 'continue'; -For : 'for'; -Switch : 'switch'; -While : 'while'; -Debugger : 'debugger'; -Function_ : 'function'; -This : 'this'; -With : 'with'; -Default : 'default'; -If : 'if'; -Throw : 'throw'; -Delete : 'delete'; -In : 'in'; -Try : 'try'; -As : 'as'; -From : 'from'; -Of : 'of'; -Yield : 'yield'; -YieldStar : 'yield*'; - -/// Future Reserved Words - -Class : 'class'; -Enum : 'enum'; -Extends : 'extends'; -Super : 'super'; -Const : 'const'; -Export : 'export'; -Import : 'import'; - -Async : 'async'; -Await : 'await'; - -/// The following tokens are also considered to be FutureReservedWords -/// when parsing strict mode - -Implements : 'implements' {this.IsStrictMode()}?; -StrictLet : 'let' {this.IsStrictMode()}?; -NonStrictLet : 'let' {!this.IsStrictMode()}?; -Private : 'private' {this.IsStrictMode()}?; -Public : 'public' {this.IsStrictMode()}?; -Interface : 'interface' {this.IsStrictMode()}?; -Package : 'package' {this.IsStrictMode()}?; -Protected : 'protected' {this.IsStrictMode()}?; -Static : 'static' {this.IsStrictMode()}?; - -/// Identifier Names and Identifiers - -Identifier: IdentifierStart IdentifierPart*; -/// String Literals -StringLiteral: - ('"' DoubleStringCharacter* '"' | '\'' SingleStringCharacter* '\'') {this.ProcessStringLiteral();} -; - -BackTick: '`' -> pushMode(TEMPLATE); - -WhiteSpaces: [\t\u000B\u000C\u0020\u00A0]+ -> channel(HIDDEN); - -LineTerminator: [\r\n\u2028\u2029] -> channel(HIDDEN); - -/// Comments - -HtmlComment : '' -> channel(HIDDEN); -CDataComment : '' -> channel(HIDDEN); -UnexpectedCharacter : . -> channel(ERROR); - -mode TEMPLATE; - -BackTickInside : '`' -> type(BackTick), popMode; -TemplateStringStartExpression : '${' {this.ProcessTemplateOpenBrace();} -> pushMode(DEFAULT_MODE); -TemplateStringAtom : ~[`]; - -// Fragment rules - -fragment DoubleStringCharacter: ~["\\\r\n] | '\\' EscapeSequence | LineContinuation; - -fragment SingleStringCharacter: ~['\\\r\n] | '\\' EscapeSequence | LineContinuation; - -fragment EscapeSequence: - CharacterEscapeSequence - | '0' // no digit ahead! TODO - | HexEscapeSequence - | UnicodeEscapeSequence - | ExtendedUnicodeEscapeSequence -; - -fragment CharacterEscapeSequence: SingleEscapeCharacter | NonEscapeCharacter; - -fragment HexEscapeSequence: 'x' HexDigit HexDigit; - -fragment UnicodeEscapeSequence: - 'u' HexDigit HexDigit HexDigit HexDigit - | 'u' '{' HexDigit HexDigit+ '}' -; - -fragment ExtendedUnicodeEscapeSequence: 'u' '{' HexDigit+ '}'; - -fragment SingleEscapeCharacter: ['"\\bfnrtv]; - -fragment NonEscapeCharacter: ~['"\\bfnrtv0-9xu\r\n]; - -fragment EscapeCharacter: SingleEscapeCharacter | [0-9] | [xu]; - -fragment LineContinuation: '\\' [\r\n\u2028\u2029]+; - -fragment HexDigit: [_0-9a-fA-F]; - -fragment DecimalIntegerLiteral: '0' | [1-9] [0-9_]*; - -fragment ExponentPart: [eE] [+-]? [0-9_]+; - -fragment IdentifierPart: IdentifierStart | [\p{Mn}] | [\p{Nd}] | [\p{Pc}] | '\u200C' | '\u200D'; - -fragment IdentifierStart: [\p{L}] | [$_] | '\\' UnicodeEscapeSequence; - -fragment RegularExpressionFirstChar: - ~[*\r\n\u2028\u2029\\/[] - | RegularExpressionBackslashSequence - | '[' RegularExpressionClassChar* ']' -; - -fragment RegularExpressionChar: - ~[\r\n\u2028\u2029\\/[] - | RegularExpressionBackslashSequence - | '[' RegularExpressionClassChar* ']' -; - -fragment RegularExpressionClassChar: ~[\r\n\u2028\u2029\]\\] | RegularExpressionBackslashSequence; - -fragment RegularExpressionBackslashSequence: '\\' ~[\r\n\u2028\u2029]; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptParser.g4 deleted file mode 100644 index f1bf54ba..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/javascript/JavaScriptParser.g4 +++ /dev/null @@ -1,584 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers (original author) and Alexandre Vitorelli (contributor -> ported to CSharp) - * Copyright (c) 2017-2020 by Ivan Kochurkin (Positive Technologies): - added ECMAScript 6 support, cleared and transformed to the universal grammar. - * Copyright (c) 2018 by Juan Alvarez (contributor -> ported to Go) - * Copyright (c) 2019 by Student Main (contributor -> ES2020) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar JavaScriptParser; - -// Insert here @header for C++ parser. - -options { - tokenVocab = JavaScriptLexer; - superClass = JavaScriptParserBase; -} - -program - : HashBangLine? sourceElements? EOF - ; - -sourceElement - : statement - ; - -statement - : block - | variableStatement - | importStatement - | exportStatement - | emptyStatement_ - | classDeclaration - | functionDeclaration - | expressionStatement - | ifStatement - | iterationStatement - | continueStatement - | breakStatement - | returnStatement - | yieldStatement - | withStatement - | labelledStatement - | switchStatement - | throwStatement - | tryStatement - | debuggerStatement - ; - -block - : '{' statementList? '}' - ; - -statementList - : statement+ - ; - -importStatement - : Import importFromBlock - ; - -importFromBlock - : importDefault? (importNamespace | importModuleItems) importFrom eos - | StringLiteral eos - ; - -importModuleItems - : '{' (importAliasName ',')* (importAliasName ','?)? '}' - ; - -importAliasName - : moduleExportName (As importedBinding)? - ; - -moduleExportName - : identifierName - | StringLiteral - ; - -// yield and await are permitted as BindingIdentifier in the grammar -importedBinding - : Identifier - | Yield - | Await - ; - -importDefault - : aliasName ',' - ; - -importNamespace - : ('*' | identifierName) (As identifierName)? - ; - -importFrom - : From StringLiteral - ; - -aliasName - : identifierName (As identifierName)? - ; - -exportStatement - : Export Default? (exportFromBlock | declaration) eos # ExportDeclaration - | Export Default singleExpression eos # ExportDefaultDeclaration - ; - -exportFromBlock - : importNamespace importFrom eos - | exportModuleItems importFrom? eos - ; - -exportModuleItems - : '{' (exportAliasName ',')* (exportAliasName ','?)? '}' - ; - -exportAliasName - : moduleExportName (As moduleExportName)? - ; - -declaration - : variableStatement - | classDeclaration - | functionDeclaration - ; - -variableStatement - : variableDeclarationList eos - ; - -variableDeclarationList - : varModifier variableDeclaration (',' variableDeclaration)* - ; - -singleVariableDeclaration - : varModifier variableDeclaration - ; - -variableDeclaration - : assignable ('=' singleExpression)? // ECMAScript 6: Array & Object Matching - ; - -emptyStatement_ - : SemiColon - ; - -expressionStatement - : {this.notOpenBraceAndNotFunction()}? expressionSequence eos - ; - -ifStatement - : If '(' expressionSequence ')' statement (Else statement)? - ; - -iterationStatement - : Do statement While '(' expressionSequence ')' eos # DoStatement - | While '(' expressionSequence ')' statement # WhileStatement - | For '(' (expressionSequence | variableDeclarationList)? ';' expressionSequence? ';' expressionSequence? ')' statement # ForStatement - | For '(' (singleExpression | singleVariableDeclaration) In expressionSequence ')' statement # ForInStatement - | For Await? '(' (singleExpression | singleVariableDeclaration) Of expressionSequence ')' statement # ForOfStatement - ; - -varModifier // let, const - ECMAScript 6 - : Var - | let_ - | Const - ; - -continueStatement - : Continue ({this.notLineTerminator()}? identifier)? eos - ; - -breakStatement - : Break ({this.notLineTerminator()}? identifier)? eos - ; - -returnStatement - : Return ({this.notLineTerminator()}? expressionSequence)? eos - ; - -yieldStatement - : (Yield | YieldStar) ({this.notLineTerminator()}? expressionSequence)? eos - ; - -withStatement - : With '(' expressionSequence ')' statement - ; - -switchStatement - : Switch '(' expressionSequence ')' caseBlock - ; - -caseBlock - : '{' caseClauses? (defaultClause caseClauses?)? '}' - ; - -caseClauses - : caseClause+ - ; - -caseClause - : Case expressionSequence ':' statementList? - ; - -defaultClause - : Default ':' statementList? - ; - -labelledStatement - : identifier ':' statement - ; - -throwStatement - : Throw {this.notLineTerminator()}? expressionSequence eos - ; - -tryStatement - : Try block (catchProduction finallyProduction? | finallyProduction) - ; - -catchProduction - : Catch ('(' assignable? ')')? block - ; - -finallyProduction - : Finally block - ; - -debuggerStatement - : Debugger eos - ; - -functionDeclaration - : Async? Function_ '*'? identifier '(' formalParameterList? ')' functionBody - ; - -classDeclaration - : Class identifier classTail - ; - -classTail - : (Extends singleExpression)? '{' classElement* '}' - ; - -classElement - : (Static | {this.n("static")}? identifier)? methodDefinition - | (Static | {this.n("static")}? identifier)? fieldDefinition - | (Static | {this.n("static")}? identifier) block - | emptyStatement_ - ; - -methodDefinition - : (Async {this.notLineTerminator()}?)? '*'? classElementName '(' formalParameterList? ')' functionBody - | '*'? getter '(' ')' functionBody - | '*'? setter '(' formalParameterList? ')' functionBody - ; - -fieldDefinition - : classElementName initializer? - ; - -classElementName - : propertyName - | privateIdentifier - ; - -privateIdentifier - : '#' identifierName - ; - -formalParameterList - : formalParameterArg (',' formalParameterArg)* (',' lastFormalParameterArg)? - | lastFormalParameterArg - ; - -formalParameterArg - : assignable ('=' singleExpression)? // ECMAScript 6: Initialization - ; - -lastFormalParameterArg // ECMAScript 6: Rest Parameter - : Ellipsis singleExpression - ; - -functionBody - : '{' sourceElements? '}' - ; - -sourceElements - : sourceElement+ - ; - -arrayLiteral - : ('[' elementList ']') - ; - -// JavaScript supports arrasys like [,,1,2,,]. -elementList - : ','* arrayElement? (','+ arrayElement) * ','* // Yes, everything is optional - ; - -arrayElement - : Ellipsis? singleExpression - ; - -propertyAssignment - : propertyName ':' singleExpression # PropertyExpressionAssignment - | '[' singleExpression ']' ':' singleExpression # ComputedPropertyExpressionAssignment - | Async? '*'? propertyName '(' formalParameterList? ')' functionBody # FunctionProperty - | getter '(' ')' functionBody # PropertyGetter - | setter '(' formalParameterArg ')' functionBody # PropertySetter - | Ellipsis? singleExpression # PropertyShorthand - ; - -propertyName - : identifierName - | StringLiteral - | numericLiteral - | '[' singleExpression ']' - ; - -arguments - : '(' (argument (',' argument)* ','?)? ')' - ; - -argument - : Ellipsis? (singleExpression | identifier) - ; - -expressionSequence - : singleExpression (',' singleExpression)* - ; - -singleExpression - : anonymousFunction # FunctionExpression - | Class identifier? classTail # ClassExpression - | singleExpression '?.' singleExpression # OptionalChainExpression - | singleExpression '?.'? '[' expressionSequence ']' # MemberIndexExpression - | singleExpression '?'? '.' '#'? identifierName # MemberDotExpression - // Split to try `new Date()` first, then `new Date`. - | New identifier arguments # NewExpression - | New singleExpression arguments # NewExpression - | New singleExpression # NewExpression - | singleExpression arguments # ArgumentsExpression - | New '.' identifier # MetaExpression // new.target - | singleExpression {this.notLineTerminator()}? '++' # PostIncrementExpression - | singleExpression {this.notLineTerminator()}? '--' # PostDecreaseExpression - | Delete singleExpression # DeleteExpression - | Void singleExpression # VoidExpression - | Typeof singleExpression # TypeofExpression - | '++' singleExpression # PreIncrementExpression - | '--' singleExpression # PreDecreaseExpression - | '+' singleExpression # UnaryPlusExpression - | '-' singleExpression # UnaryMinusExpression - | '~' singleExpression # BitNotExpression - | '!' singleExpression # NotExpression - | Await singleExpression # AwaitExpression - | singleExpression '**' singleExpression # PowerExpression - | singleExpression ('*' | '/' | '%') singleExpression # MultiplicativeExpression - | singleExpression ('+' | '-') singleExpression # AdditiveExpression - | singleExpression '??' singleExpression # CoalesceExpression - | singleExpression ('<<' | '>>' | '>>>') singleExpression # BitShiftExpression - | singleExpression ('<' | '>' | '<=' | '>=') singleExpression # RelationalExpression - | singleExpression Instanceof singleExpression # InstanceofExpression - | singleExpression In singleExpression # InExpression - | singleExpression ('==' | '!=' | '===' | '!==') singleExpression # EqualityExpression - | singleExpression '&' singleExpression # BitAndExpression - | singleExpression '^' singleExpression # BitXOrExpression - | singleExpression '|' singleExpression # BitOrExpression - | singleExpression '&&' singleExpression # LogicalAndExpression - | singleExpression '||' singleExpression # LogicalOrExpression - | singleExpression '?' singleExpression ':' singleExpression # TernaryExpression - | singleExpression '=' singleExpression # AssignmentExpression - | singleExpression assignmentOperator singleExpression # AssignmentOperatorExpression - | Import '(' singleExpression ')' # ImportExpression - | singleExpression templateStringLiteral # TemplateStringExpression // ECMAScript 6 - | yieldStatement # YieldExpression // ECMAScript 6 - | This # ThisExpression - | identifier # IdentifierExpression - | Super # SuperExpression - | literal # LiteralExpression - | arrayLiteral # ArrayLiteralExpression - | objectLiteral # ObjectLiteralExpression - | '(' expressionSequence ')' # ParenthesizedExpression - ; - -initializer - // TODO: must be `= AssignmentExpression` and we have such label alredy but it doesn't respect the specification. - // See https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#prod-Initializer - : '=' singleExpression - ; - -assignable - : identifier - | keyword - | arrayLiteral - | objectLiteral - ; - -objectLiteral - : '{' (propertyAssignment (',' propertyAssignment)* ','?)? '}' - ; - -anonymousFunction - : functionDeclaration # NamedFunction - | Async? Function_ '*'? '(' formalParameterList? ')' functionBody # AnonymousFunctionDecl - | Async? arrowFunctionParameters '=>' arrowFunctionBody # ArrowFunction - ; - -arrowFunctionParameters - : propertyName - | '(' formalParameterList? ')' - ; - -arrowFunctionBody - : singleExpression - | functionBody - ; - -assignmentOperator - : '*=' - | '/=' - | '%=' - | '+=' - | '-=' - | '<<=' - | '>>=' - | '>>>=' - | '&=' - | '^=' - | '|=' - | '**=' - | '??=' - ; - -literal - : NullLiteral - | BooleanLiteral - | StringLiteral - | templateStringLiteral - | RegularExpressionLiteral - | numericLiteral - | bigintLiteral - ; - -templateStringLiteral - : BackTick templateStringAtom* BackTick - ; - -templateStringAtom - : TemplateStringAtom - | TemplateStringStartExpression singleExpression TemplateCloseBrace - ; - -numericLiteral - : DecimalLiteral - | HexIntegerLiteral - | OctalIntegerLiteral - | OctalIntegerLiteral2 - | BinaryIntegerLiteral - ; - -bigintLiteral - : BigDecimalIntegerLiteral - | BigHexIntegerLiteral - | BigOctalIntegerLiteral - | BigBinaryIntegerLiteral - ; - -getter - : {this.n("get")}? identifier classElementName - ; - -setter - : {this.n("set")}? identifier classElementName - ; - -identifierName - : identifier - | reservedWord - ; - -identifier - : Identifier - | NonStrictLet - | Async - | As - | From - | Yield - | Of - ; - -reservedWord - : keyword - | NullLiteral - | BooleanLiteral - ; - -keyword - : Break - | Do - | Instanceof - | Typeof - | Case - | Else - | New - | Var - | Catch - | Finally - | Return - | Void - | Continue - | For - | Switch - | While - | Debugger - | Function_ - | This - | With - | Default - | If - | Throw - | Delete - | In - | Try - | Class - | Enum - | Extends - | Super - | Const - | Export - | Import - | Implements - | let_ - | Private - | Public - | Interface - | Package - | Protected - | Static - | Yield - | YieldStar - | Async - | Await - | From - | As - | Of - ; - -let_ - : NonStrictLet - | StrictLet - ; - -eos - : SemiColon - | EOF - | {this.lineTerminatorAhead()}? - | {this.closeBrace()}? - ; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinLexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinLexer.g4 deleted file mode 100644 index 88f51a6a..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinLexer.g4 +++ /dev/null @@ -1,450 +0,0 @@ -/** - * Kotlin Grammar for ANTLR v4 - * - * Based on: - * jetbrains.github.io/kotlin-spec/#_grammars_and_parsing - * and - * kotlinlang.org/docs/reference/grammar.html - * - * Tested on - * https://github.com/JetBrains/kotlin/tree/master/compiler/testData/psi - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar KotlinLexer; - -import UnicodeClasses; - -ShebangLine: '#!' ~[\r\n]*; - -DelimitedComment: '/*' ( DelimitedComment | .)*? '*/' -> channel(HIDDEN); - -LineComment: '//' ~[\r\n]* -> channel(HIDDEN); - -WS: [\u0020\u0009\u000C] -> channel(HIDDEN); - -NL: '\n' | '\r' '\n'?; - -fragment Hidden: DelimitedComment | LineComment | WS; - -//SEPARATORS & OPERATIONS - -RESERVED : '...'; -DOT : '.'; -COMMA : ','; -LPAREN : '(' -> pushMode(Inside); -RPAREN : ')' -> popMode; -LSQUARE : '[' -> pushMode(Inside); -RSQUARE : ']' -> popMode; -LCURL : '{' -> pushMode(DEFAULT_MODE); -RCURL : '}' -> popMode; -MULT : '*'; -MOD : '%'; -DIV : '/'; -ADD : '+'; -SUB : '-'; -INCR : '++'; -DECR : '--'; -CONJ : '&&'; -DISJ : '||'; -EXCL_WS : '!' Hidden; -EXCL_NO_WS : '!'; -COLON : ':'; -SEMICOLON : ';'; -ASSIGNMENT : '='; -ADD_ASSIGNMENT : '+='; -SUB_ASSIGNMENT : '-='; -MULT_ASSIGNMENT : '*='; -DIV_ASSIGNMENT : '/='; -MOD_ASSIGNMENT : '%='; -ARROW : '->'; -DOUBLE_ARROW : '=>'; -RANGE : '..'; -COLONCOLON : '::'; -DOUBLE_SEMICOLON : ';;'; -HASH : '#'; -AT : '@'; -AT_WS : AT (Hidden | NL); -/* Disambiguating ? without spaces and with spaces (sometimes required) */ -QUEST_WS : '?' Hidden; -QUEST_NO_WS : '?'; -LANGLE : '<'; -RANGLE : '>'; -LE : '<='; -GE : '>='; -EXCL_EQ : '!='; -EXCL_EQEQ : '!=='; -AS_SAFE : 'as?'; -EQEQ : '=='; -EQEQEQ : '==='; -SINGLE_QUOTE : '\''; - -//KEYWORDS - -RETURN_AT : 'return@' Identifier; -CONTINUE_AT : 'continue@' Identifier; -BREAK_AT : 'break@' Identifier; - -THIS_AT : 'this@' Identifier; -SUPER_AT : 'super@' Identifier; - -PACKAGE : 'package'; -IMPORT : 'import'; -CLASS : 'class'; -INTERFACE : 'interface'; -FUN : 'fun'; -OBJECT : 'object'; -VAL : 'val'; -VAR : 'var'; -TYPE_ALIAS : 'typealias'; -CONSTRUCTOR : 'constructor'; -BY : 'by'; -COMPANION : 'companion'; -INIT : 'init'; -THIS : 'this'; -SUPER : 'super'; -TYPEOF : 'typeof'; -WHERE : 'where'; -IF : 'if'; -ELSE : 'else'; -WHEN : 'when'; -TRY : 'try'; -CATCH : 'catch'; -FINALLY : 'finally'; -FOR : 'for'; -DO : 'do'; -WHILE : 'while'; -THROW : 'throw'; -RETURN : 'return'; -CONTINUE : 'continue'; -BREAK : 'break'; -AS : 'as'; -IS : 'is'; -IN : 'in'; -NOT_IS : '!is' (Hidden | NL); -NOT_IN : '!in' (Hidden | NL); -OUT : 'out'; -GETTER : 'get'; -SETTER : 'set'; -DYNAMIC : 'dynamic'; -AT_FILE : '@file'; -AT_FIELD : '@field'; -AT_PROPERTY : '@property'; -AT_GET : '@get'; -AT_SET : '@set'; -AT_RECEIVER : '@receiver'; -AT_PARAM : '@param'; -AT_SETPARAM : '@setparam'; -AT_DELEGATE : '@delegate'; - -//MODIFIERS - -PUBLIC : 'public'; -PRIVATE : 'private'; -PROTECTED : 'protected'; -INTERNAL : 'internal'; -ENUM : 'enum'; -SEALED : 'sealed'; -ANNOTATION : 'annotation'; -DATA : 'data'; -INNER : 'inner'; -TAILREC : 'tailrec'; -OPERATOR : 'operator'; -INLINE : 'inline'; -INFIX : 'infix'; -EXTERNAL : 'external'; -SUSPEND : 'suspend'; -OVERRIDE : 'override'; -ABSTRACT : 'abstract'; -FINAL : 'final'; -OPEN : 'open'; -CONST : 'const'; -LATEINIT : 'lateinit'; -VARARG : 'vararg'; -NOINLINE : 'noinline'; -CROSSINLINE : 'crossinline'; -REIFIED : 'reified'; - -EXPECT : 'expect'; -ACTUAL : 'actual'; - -QUOTE_OPEN : '"' -> pushMode(LineString); -TRIPLE_QUOTE_OPEN : '"""' -> pushMode(MultiLineString); - -RealLiteral: FloatLiteral | DoubleLiteral; - -FloatLiteral: DoubleLiteral [fF] | DecDigits [fF]; - -fragment DecDigitOrSeparator : DecDigit | '_'; -fragment DecDigits : DecDigit DecDigitOrSeparator* DecDigit | DecDigit; -fragment DoubleExponent : [eE] [+-]? DecDigits; - -DoubleLiteral: DecDigits? '.' DecDigits DoubleExponent? | DecDigits DoubleExponent; - -LongLiteral: (IntegerLiteral | HexLiteral | BinLiteral) 'L'; - -IntegerLiteral: - DecDigitNoZero DecDigitOrSeparator* DecDigit - | DecDigit // including '0' -; - -fragment UnicodeDigit: UNICODE_CLASS_ND; - -fragment DecDigit: '0' ..'9'; - -fragment DecDigitNoZero: '1' ..'9'; - -fragment HexDigitOrSeparator: HexDigit | '_'; - -HexLiteral: '0' [xX] HexDigit HexDigitOrSeparator* HexDigit | '0' [xX] HexDigit; - -fragment HexDigit: [0-9a-fA-F]; - -fragment BinDigitOrSeparator: BinDigit | '_'; - -BinLiteral: '0' [bB] BinDigit BinDigitOrSeparator* BinDigit | '0' [bB] BinDigit; - -fragment BinDigit: [01]; - -BooleanLiteral: 'true' | 'false'; - -NullLiteral: 'null'; - -Identifier: - (Letter | '_') (Letter | '_' | UnicodeDigit)* - | '`' ~('\r' | '\n' | '`' | '[' | ']' | '<' | '>')+ '`' -; - -fragment IdentifierOrSoftKey: - Identifier //soft keywords: - | ABSTRACT - | ANNOTATION - | BY - | CATCH - | COMPANION - | CONSTRUCTOR - | CROSSINLINE - | DATA - | DYNAMIC - | ENUM - | EXTERNAL - | FINAL - | FINALLY - | GETTER - | IMPORT - | INFIX - | INIT - | INLINE - | INNER - | INTERNAL - | LATEINIT - | NOINLINE - | OPEN - | OPERATOR - | OUT - | OVERRIDE - | PRIVATE - | PROTECTED - | PUBLIC - | REIFIED - | SEALED - | TAILREC - | SETTER - | VARARG - | WHERE - | EXPECT - | ACTUAL - //strong keywords - | CONST - | SUSPEND -; - -IdentifierAt: IdentifierOrSoftKey '@'; - -FieldIdentifier: '$' IdentifierOrSoftKey; // why is this even needed? - -CharacterLiteral: '\'' (EscapeSeq | ~[\n\r'\\]) '\''; - -fragment EscapeSeq: UniCharacterLiteral | EscapedIdentifier; - -fragment UniCharacterLiteral: '\\' 'u' HexDigit HexDigit HexDigit HexDigit; - -fragment EscapedIdentifier: '\\' ('t' | 'b' | 'r' | 'n' | '\'' | '"' | '\\' | '$'); - -fragment Letter: - UNICODE_CLASS_LL - | UNICODE_CLASS_LM - | UNICODE_CLASS_LO - | UNICODE_CLASS_LT - | UNICODE_CLASS_LU - | UNICODE_CLASS_NL -; - -ErrorCharacter: .; - -mode Inside; - -Inside_RPAREN : RPAREN -> popMode, type(RPAREN); -Inside_RSQUARE : RSQUARE -> popMode, type(RSQUARE); -Inside_LPAREN : LPAREN -> pushMode(Inside), type(LPAREN); -Inside_LSQUARE : LSQUARE -> pushMode(Inside), type(LSQUARE); -Inside_LCURL : LCURL -> pushMode(DEFAULT_MODE), type(LCURL); -Inside_RCURL : RCURL -> popMode, type(RCURL); - -Inside_DOT : DOT -> type(DOT); -Inside_COMMA : COMMA -> type(COMMA); -Inside_MULT : MULT -> type(MULT); -Inside_MOD : MOD -> type(MOD); -Inside_DIV : DIV -> type(DIV); -Inside_ADD : ADD -> type(ADD); -Inside_SUB : SUB -> type(SUB); -Inside_INCR : INCR -> type(INCR); -Inside_DECR : DECR -> type(DECR); -Inside_CONJ : CONJ -> type(CONJ); -Inside_DISJ : DISJ -> type(DISJ); -Inside_EXCL_WS : '!' (Hidden | NL) -> type(EXCL_WS); -Inside_EXCL_NO_WS : EXCL_NO_WS -> type(EXCL_NO_WS); -Inside_COLON : COLON -> type(COLON); -Inside_SEMICOLON : SEMICOLON -> type(SEMICOLON); -Inside_ASSIGNMENT : ASSIGNMENT -> type(ASSIGNMENT); -Inside_ADD_ASSIGNMENT : ADD_ASSIGNMENT -> type(ADD_ASSIGNMENT); -Inside_SUB_ASSIGNMENT : SUB_ASSIGNMENT -> type(SUB_ASSIGNMENT); -Inside_MULT_ASSIGNMENT : MULT_ASSIGNMENT -> type(MULT_ASSIGNMENT); -Inside_DIV_ASSIGNMENT : DIV_ASSIGNMENT -> type(DIV_ASSIGNMENT); -Inside_MOD_ASSIGNMENT : MOD_ASSIGNMENT -> type(MOD_ASSIGNMENT); -Inside_ARROW : ARROW -> type(ARROW); -Inside_DOUBLE_ARROW : DOUBLE_ARROW -> type(DOUBLE_ARROW); -Inside_RANGE : RANGE -> type(RANGE); -Inside_RESERVED : RESERVED -> type(RESERVED); -Inside_COLONCOLON : COLONCOLON -> type(COLONCOLON); -Inside_DOUBLE_SEMICOLON : DOUBLE_SEMICOLON -> type(DOUBLE_SEMICOLON); -Inside_HASH : HASH -> type(HASH); -Inside_AT : AT -> type(AT); -Inside_QUEST_WS : '?' (Hidden | NL) -> type(QUEST_WS); -Inside_QUEST_NO_WS : QUEST_NO_WS -> type(QUEST_NO_WS); -Inside_LANGLE : LANGLE -> type(LANGLE); -Inside_RANGLE : RANGLE -> type(RANGLE); -Inside_LE : LE -> type(LE); -Inside_GE : GE -> type(GE); -Inside_EXCL_EQ : EXCL_EQ -> type(EXCL_EQ); -Inside_EXCL_EQEQ : EXCL_EQEQ -> type(EXCL_EQEQ); -Inside_IS : IS -> type(IS); -Inside_NOT_IS : NOT_IS -> type(NOT_IS); -Inside_NOT_IN : NOT_IN -> type(NOT_IN); -Inside_AS : AS -> type(AS); -Inside_AS_SAFE : AS_SAFE -> type(AS_SAFE); -Inside_EQEQ : EQEQ -> type(EQEQ); -Inside_EQEQEQ : EQEQEQ -> type(EQEQEQ); -Inside_SINGLE_QUOTE : SINGLE_QUOTE -> type(SINGLE_QUOTE); -Inside_QUOTE_OPEN : QUOTE_OPEN -> pushMode(LineString), type(QUOTE_OPEN); -Inside_TRIPLE_QUOTE_OPEN: - TRIPLE_QUOTE_OPEN -> pushMode(MultiLineString), type(TRIPLE_QUOTE_OPEN) -; - -Inside_VAL : VAL -> type(VAL); -Inside_VAR : VAR -> type(VAR); -Inside_FUN : FUN -> type(FUN); -Inside_OBJECT : OBJECT -> type(OBJECT); -Inside_SUPER : SUPER -> type(SUPER); -Inside_IN : IN -> type(IN); -Inside_OUT : OUT -> type(OUT); -Inside_AT_FIELD : AT_FIELD -> type(AT_FIELD); -Inside_AT_FILE : AT_FILE -> type(AT_FILE); -Inside_AT_PROPERTY : AT_PROPERTY -> type(AT_PROPERTY); -Inside_AT_GET : AT_GET -> type(AT_GET); -Inside_AT_SET : AT_SET -> type(AT_SET); -Inside_AT_RECEIVER : AT_RECEIVER -> type(AT_RECEIVER); -Inside_AT_PARAM : AT_PARAM -> type(AT_PARAM); -Inside_AT_SETPARAM : AT_SETPARAM -> type(AT_SETPARAM); -Inside_AT_DELEGATE : AT_DELEGATE -> type(AT_DELEGATE); -Inside_THROW : THROW -> type(THROW); -Inside_RETURN : RETURN -> type(RETURN); -Inside_CONTINUE : CONTINUE -> type(CONTINUE); -Inside_BREAK : BREAK -> type(BREAK); -Inside_RETURN_AT : RETURN_AT -> type(RETURN_AT); -Inside_CONTINUE_AT : CONTINUE_AT -> type(CONTINUE_AT); -Inside_BREAK_AT : BREAK_AT -> type(BREAK_AT); -Inside_IF : IF -> type(IF); -Inside_ELSE : ELSE -> type(ELSE); -Inside_WHEN : WHEN -> type(WHEN); -Inside_TRY : TRY -> type(TRY); -Inside_CATCH : CATCH -> type(CATCH); -Inside_FINALLY : FINALLY -> type(FINALLY); -Inside_FOR : FOR -> type(FOR); -Inside_DO : DO -> type(DO); -Inside_WHILE : WHILE -> type(WHILE); - -Inside_PUBLIC : PUBLIC -> type(PUBLIC); -Inside_PRIVATE : PRIVATE -> type(PRIVATE); -Inside_PROTECTED : PROTECTED -> type(PROTECTED); -Inside_INTERNAL : INTERNAL -> type(INTERNAL); -Inside_ENUM : ENUM -> type(ENUM); -Inside_SEALED : SEALED -> type(SEALED); -Inside_ANNOTATION : ANNOTATION -> type(ANNOTATION); -Inside_DATA : DATA -> type(DATA); -Inside_INNER : INNER -> type(INNER); -Inside_TAILREC : TAILREC -> type(TAILREC); -Inside_OPERATOR : OPERATOR -> type(OPERATOR); -Inside_INLINE : INLINE -> type(INLINE); -Inside_INFIX : INFIX -> type(INFIX); -Inside_EXTERNAL : EXTERNAL -> type(EXTERNAL); -Inside_SUSPEND : SUSPEND -> type(SUSPEND); -Inside_OVERRIDE : OVERRIDE -> type(OVERRIDE); -Inside_ABSTRACT : ABSTRACT -> type(ABSTRACT); -Inside_FINAL : FINAL -> type(FINAL); -Inside_OPEN : OPEN -> type(OPEN); -Inside_CONST : CONST -> type(CONST); -Inside_LATEINIT : LATEINIT -> type(LATEINIT); -Inside_VARARG : VARARG -> type(VARARG); -Inside_NOINLINE : NOINLINE -> type(NOINLINE); -Inside_CROSSINLINE : CROSSINLINE -> type(CROSSINLINE); -Inside_REIFIED : REIFIED -> type(REIFIED); -Inside_EXPECT : EXPECT -> type(EXPECT); -Inside_ACTUAL : ACTUAL -> type(ACTUAL); - -Inside_BooleanLiteral : BooleanLiteral -> type(BooleanLiteral); -Inside_IntegerLiteral : IntegerLiteral -> type(IntegerLiteral); -Inside_HexLiteral : HexLiteral -> type(HexLiteral); -Inside_BinLiteral : BinLiteral -> type(BinLiteral); -Inside_CharacterLiteral : CharacterLiteral -> type(CharacterLiteral); -Inside_RealLiteral : RealLiteral -> type(RealLiteral); -Inside_NullLiteral : NullLiteral -> type(NullLiteral); -Inside_LongLiteral : LongLiteral -> type(LongLiteral); - -Inside_Identifier : Identifier -> type(Identifier); -Inside_IdentifierAt : IdentifierAt -> type(IdentifierAt); -Inside_Comment : (LineComment | DelimitedComment) -> channel(HIDDEN); -Inside_WS : WS -> channel(HIDDEN); -Inside_NL : NL -> channel(HIDDEN); - -mode LineString; - -QUOTE_CLOSE: '"' -> popMode; - -LineStrRef: FieldIdentifier; - -LineStrText: ~('\\' | '"' | '$')+ | '$'; - -LineStrEscapedChar: EscapedIdentifier | UniCharacterLiteral; - -LineStrExprStart: '${' -> pushMode(DEFAULT_MODE); - -mode MultiLineString; - -TRIPLE_QUOTE_CLOSE: MultiLineStringQuote? '"""' -> popMode; - -MultiLineStringQuote: '"'+; - -MultiLineStrRef: FieldIdentifier; - -MultiLineStrText: - ~('"' | '$')+ - | '$' // multiline does not support escaping, so only '$' should be disallowed -; - -MultiLineStrExprStart: '${' -> pushMode(DEFAULT_MODE); - -MultiLineNL: NL -> type(NL); \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinParser.g4 deleted file mode 100644 index 28cb5946..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/KotlinParser.g4 +++ /dev/null @@ -1,893 +0,0 @@ -/** - * Kotlin Grammar for ANTLR v4 - * - * Based on: - * jetbrains.github.io/kotlin-spec/#_grammars_and_parsing - * and - * kotlinlang.org/docs/reference/grammar.html - * - * Tested on - * https://github.com/JetBrains/kotlin/tree/master/compiler/testData/psi - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar KotlinParser; - -options { - tokenVocab = KotlinLexer; -} - -kotlinFile - : shebangLine? NL* fileAnnotation* packageHeader importList topLevelObject* EOF - ; - -script - : shebangLine? NL* fileAnnotation* packageHeader importList (statement semi)* EOF - ; - -fileAnnotation - : '@file' NL* ':' NL* ('[' unescapedAnnotation+ ']' | unescapedAnnotation) NL* - ; - -packageHeader - : ('package' identifier semi?)? - ; - -importList - : importHeader* - ; - -importHeader - : 'import' identifier ('.' '*' | importAlias)? semi? - ; - -importAlias - : 'as' simpleIdentifier - ; - -topLevelObject - : declaration semis? - ; - -classDeclaration - : modifiers? ('class' | 'interface') NL* simpleIdentifier (NL* typeParameters)? ( - NL* primaryConstructor - )? (NL* ':' NL* delegationSpecifiers)? (NL* typeConstraints)? ( - NL* classBody - | NL* enumClassBody - )? - ; - -primaryConstructor - : (modifiers? 'constructor' NL*)? classParameters - ; - -classParameters - : '(' NL* (classParameter (NL* ',' NL* classParameter)*)? NL* ','? ')' - ; - -classParameter - : modifiers? ('val' | 'var')? NL* simpleIdentifier ':' NL* type_ (NL* '=' NL* expression)? - ; - -delegationSpecifiers - : annotatedDelegationSpecifier (NL* ',' NL* annotatedDelegationSpecifier)* - ; - -annotatedDelegationSpecifier - : annotation* NL* delegationSpecifier - ; - -delegationSpecifier - : constructorInvocation - | explicitDelegation - | userType - | functionType - ; - -constructorInvocation - : userType valueArguments - ; - -explicitDelegation - : (userType | functionType) NL* 'by' NL* expression - ; - -classBody - : '{' NL* classMemberDeclarations NL* '}' - ; - -classMemberDeclarations - : (classMemberDeclaration semis?)* - ; - -classMemberDeclaration - : declaration - | companionObject - | anonymousInitializer - | secondaryConstructor - ; - -anonymousInitializer - : 'init' NL* block - ; - -secondaryConstructor - : modifiers? 'constructor' NL* functionValueParameters (NL* ':' NL* constructorDelegationCall)? NL* block? - ; - -constructorDelegationCall - : 'this' NL* valueArguments - | 'super' NL* valueArguments - ; - -enumClassBody - : '{' NL* enumEntries? (NL* ';' NL* classMemberDeclarations)? NL* '}' - ; - -enumEntries - : enumEntry (NL* ',' NL* enumEntry)* NL* ','? - ; - -enumEntry - : (modifiers NL*)? simpleIdentifier (NL* valueArguments)? (NL* classBody)? - ; - -functionDeclaration - : modifiers? 'fun' (NL* typeParameters)? (NL* receiverType NL* '.')? NL* simpleIdentifier NL* functionValueParameters ( - NL* ':' NL* type_ - )? (NL* typeConstraints)? (NL* functionBody)? - ; - -functionValueParameters - : '(' NL* (functionValueParameter (NL* ',' NL* functionValueParameter)*)? NL* ','? ')' - ; - -functionValueParameter - : modifiers? parameter (NL* '=' NL* expression)? - ; - -parameter - : simpleIdentifier NL* ':' NL* type_ - ; - -setterParameter - : simpleIdentifier NL* (':' NL* type_)? - ; - -functionBody - : block - | '=' NL* expression - ; - -objectDeclaration - : modifiers? 'object' NL* simpleIdentifier (NL* ':' NL* delegationSpecifiers)? (NL* classBody)? - ; - -companionObject - : modifiers? 'companion' NL* 'object' (NL* simpleIdentifier)? ( - NL* ':' NL* delegationSpecifiers - )? (NL* classBody)? - ; - -propertyDeclaration - : modifiers? ('val' | 'var') (NL* typeParameters)? (NL* receiverType NL* '.')? ( - NL* (multiVariableDeclaration | variableDeclaration) - ) (NL* typeConstraints)? (NL* ('=' NL* expression | propertyDelegate))? (NL+ ';')? NL* ( - getter? (NL* semi? setter)? - | setter? (NL* semi? getter)? - ) - /* - XXX: actually, it's not that simple. You can put semi only on the same line as getter, but any other semicolons - between property and getter are forbidden - Is this a bug in kotlin parser? Who knows. - */ - ; - -multiVariableDeclaration - : '(' NL* variableDeclaration (NL* ',' NL* variableDeclaration)* NL* ')' - ; - -variableDeclaration - : annotation* NL* simpleIdentifier (NL* ':' NL* type_)? - ; - -propertyDelegate - : 'by' NL* expression - ; - -getter - : modifiers? 'get' - | modifiers? 'get' NL* '(' NL* ')' (NL* ':' NL* type_)? NL* functionBody - ; - -setter - : modifiers? 'set' - | modifiers? 'set' NL* '(' (annotation | parameterModifier)* setterParameter ')' ( - NL* ':' NL* type_ - )? NL* functionBody - ; - -typeAlias - : modifiers? 'typealias' NL* simpleIdentifier (NL* typeParameters)? NL* '=' NL* type_ - ; - -typeParameters - : '<' NL* typeParameter (NL* ',' NL* typeParameter)* NL* ','? '>' - ; - -typeParameter - : typeParameterModifiers? NL* simpleIdentifier (NL* ':' NL* type_)? - ; - -typeParameterModifiers - : typeParameterModifier+ - ; - -typeParameterModifier - : reificationModifier NL* - | varianceModifier NL* - | annotation - ; - -type_ - : typeModifiers? (parenthesizedType | nullableType | typeReference | functionType) - ; - -typeModifiers - : typeModifier+ - ; - -typeModifier - : annotation - | 'suspend' NL* - ; - -parenthesizedType - : '(' NL* type_ NL* ')' - ; - -nullableType - : (typeReference | parenthesizedType) NL* quest+ - ; - -typeReference - : userType - | 'dynamic' // do we need a separate dynamic support here? - ; - -functionType - : (receiverType NL* '.' NL*)? functionTypeParameters NL* '->' NL* type_ - ; - -receiverType - : typeModifiers? (parenthesizedType | nullableType | typeReference) - ; - -userType - : simpleUserType (NL* '.' NL* simpleUserType)* - ; - -parenthesizedUserType - : '(' NL* userType NL* ')' - | '(' NL* parenthesizedUserType NL* ')' - ; - -simpleUserType - : simpleIdentifier (NL* typeArguments)? - ; - -functionTypeParameters - : '(' NL* (parameter | type_)? (NL* ',' NL* (parameter | type_))* NL* ')' - ; - -typeConstraints - : 'where' NL* typeConstraint (NL* ',' NL* typeConstraint)* - ; - -typeConstraint - : annotation* simpleIdentifier NL* ':' NL* type_ - ; - -block - : '{' NL* statements NL* '}' - ; - -statements - : (statement ((';' | NL)+ statement)* semis?)? - ; - -statement - : (label | annotation)* (declaration | assignment | loopStatement | expression) - ; - -declaration - : classDeclaration - | objectDeclaration - | functionDeclaration - | propertyDeclaration - | typeAlias - ; - -assignment - : directlyAssignableExpression '=' NL* expression - | assignableExpression assignmentAndOperator NL* expression - ; - -expression - : disjunction - ; - -disjunction - : conjunction (NL* '||' NL* conjunction)* - ; - -conjunction - : equality (NL* '&&' NL* equality)* - ; - -equality - : comparison (/* NO NL! */ equalityOperator NL* comparison)* - ; - -comparison - : infixOperation (/* NO NL! */ comparisonOperator NL* infixOperation)? - ; - -infixOperation - : elvisExpression (/* NO NL! */ inOperator NL* elvisExpression | isOperator NL* type_)* - ; - -elvisExpression - : infixFunctionCall (NL* elvis NL* infixFunctionCall)* - ; - -infixFunctionCall - : rangeExpression (/* NO NL! */ simpleIdentifier NL* rangeExpression)* - ; - -rangeExpression - : additiveExpression (/* NO NL! */ '..' NL* additiveExpression)* - ; - -additiveExpression - : multiplicativeExpression (/* NO NL! */ additiveOperator NL* multiplicativeExpression)* - ; - -multiplicativeExpression - : asExpression (/* NO NL! */ multiplicativeOperator NL* asExpression)* - ; - -asExpression - : prefixUnaryExpression (NL* asOperator NL* type_)? - ; - -prefixUnaryExpression - : unaryPrefix* postfixUnaryExpression - ; - -unaryPrefix - : annotation - | label - | prefixUnaryOperator NL* - ; - -postfixUnaryExpression - : primaryExpression - | primaryExpression postfixUnarySuffix+ - ; - -postfixUnarySuffix - : postfixUnaryOperator - | typeArguments - | callSuffix - | indexingSuffix - | navigationSuffix - ; - -directlyAssignableExpression - : postfixUnaryExpression assignableSuffix - | simpleIdentifier - ; - -assignableExpression - : prefixUnaryExpression - ; - -assignableSuffix - : typeArguments - | indexingSuffix - | navigationSuffix - ; - -indexingSuffix - : '[' NL* expression (NL* ',' NL* expression)* NL* ']' - ; - -navigationSuffix - : NL* memberAccessOperator NL* (simpleIdentifier | parenthesizedExpression | 'class') - ; - -callSuffix - : typeArguments? valueArguments? annotatedLambda - | typeArguments? valueArguments - ; - -annotatedLambda - : annotation* label? NL* lambdaLiteral - ; - -valueArguments - : '(' NL* ')' - | '(' NL* valueArgument (NL* ',' NL* valueArgument)* NL* ','? ')' - ; - -typeArguments - : '<' NL* typeProjection (NL* ',' NL* typeProjection)* NL* ','? '>' - ; - -typeProjection - : typeProjectionModifiers? type_ - | '*' - ; - -typeProjectionModifiers - : typeProjectionModifier+ - ; - -typeProjectionModifier - : varianceModifier NL* - | annotation - ; - -valueArgument - : annotation? NL* (simpleIdentifier NL* '=' NL*)? '*'? NL* expression - ; - -primaryExpression - : parenthesizedExpression - | literalConstant - | stringLiteral - | simpleIdentifier - | callableReference - | functionLiteral - | objectLiteral - | collectionLiteral - | thisExpression - | superExpression - | ifExpression - | whenExpression - | tryExpression - | jumpExpression - ; - -parenthesizedExpression - : '(' NL* expression NL* ')' - ; - -collectionLiteral - : '[' NL* expression (NL* ',' NL* expression)* NL* ','? ']' - | '[' NL* ']' - ; - -literalConstant - : BooleanLiteral - | IntegerLiteral - | HexLiteral - | BinLiteral - | CharacterLiteral - | RealLiteral - | NullLiteral - | LongLiteral - ; - -stringLiteral - : lineStringLiteral - | multiLineStringLiteral - ; - -lineStringLiteral - : QUOTE_OPEN (lineStringContent | lineStringExpression)* QUOTE_CLOSE - ; - -multiLineStringLiteral // why is lineStringLiteral here? there is no escaping in multiline strings - : TRIPLE_QUOTE_OPEN (multiLineStringContent | multiLineStringExpression | MultiLineStringQuote)* TRIPLE_QUOTE_CLOSE - ; - -lineStringContent - : LineStrText - | LineStrEscapedChar - | LineStrRef - ; - -lineStringExpression - : LineStrExprStart expression '}' - ; - -multiLineStringContent - : MultiLineStrText - | MultiLineStringQuote - | MultiLineStrRef - ; - -multiLineStringExpression - : MultiLineStrExprStart NL* expression NL* '}' - ; - -lambdaLiteral // anonymous functions? - : LCURL NL* statements NL* RCURL - | LCURL NL* lambdaParameters? NL* ARROW NL* statements NL* '}' - ; - -lambdaParameters - : lambdaParameter (NL* COMMA NL* lambdaParameter)* COMMA? - ; - -lambdaParameter - : variableDeclaration - | multiVariableDeclaration (NL* COLON NL* type_)? - ; - -anonymousFunction - : 'fun' (NL* type_ NL* '.')? NL* functionValueParameters (NL* ':' NL* type_)? ( - NL* typeConstraints - )? (NL* functionBody)? - ; - -functionLiteral - : lambdaLiteral - | anonymousFunction - ; - -objectLiteral - : 'object' NL* ':' NL* delegationSpecifiers (NL* classBody)? - | 'object' NL* classBody - ; - -thisExpression - : 'this' - | THIS_AT - ; - -superExpression - : 'super' ('<' NL* type_ NL* '>')? ('@' simpleIdentifier)? - | SUPER_AT - ; - -controlStructureBody - : block - | statement - ; - -ifExpression - : 'if' NL* '(' NL* expression NL* ')' NL* controlStructureBody ( - ';'? NL* 'else' NL* controlStructureBody - )? - | 'if' NL* '(' NL* expression NL* ')' NL* (';' NL*)? 'else' NL* controlStructureBody - ; - -whenExpression - : 'when' NL* ('(' expression ')')? NL* '{' NL* (whenEntry NL*)* NL* '}' - ; - -whenEntry - : whenCondition (NL* ',' NL* whenCondition)* NL* '->' NL* controlStructureBody semi? - | 'else' NL* '->' NL* controlStructureBody semi? - ; - -whenCondition - : expression - | rangeTest - | typeTest - ; - -rangeTest - : inOperator NL* expression - ; - -typeTest - : isOperator NL* type_ - ; - -tryExpression - : 'try' NL* block ((NL* catchBlock)+ (NL* finallyBlock)? | NL* finallyBlock) - ; - -catchBlock - : 'catch' NL* '(' annotation* simpleIdentifier ':' userType ')' NL* block - ; - -finallyBlock - : 'finally' NL* block - ; - -loopStatement - : forStatement - | whileStatement - | doWhileStatement - ; - -forStatement - : 'for' NL* '(' annotation* (variableDeclaration | multiVariableDeclaration) 'in' expression ')' NL* controlStructureBody? - ; - -whileStatement - : 'while' NL* '(' expression ')' NL* controlStructureBody - | 'while' NL* '(' expression ')' NL* ';' - ; - -doWhileStatement - : 'do' NL* controlStructureBody? NL* 'while' NL* '(' expression ')' - ; - -jumpExpression - : 'throw' NL* expression - | ('return' | RETURN_AT) expression? - | 'continue' - | CONTINUE_AT - | 'break' - | BREAK_AT - ; - -callableReference // ?:: here is not an actual operator, it's just a lexer hack to avoid (?: + :) vs (? + ::) ambiguity - : (receiverType? NL* '::' NL* (simpleIdentifier | 'class')) - ; - -assignmentAndOperator - : '+=' - | '-=' - | '*=' - | '/=' - | '%=' - ; - -equalityOperator - : '!=' - | '!==' - | '==' - | '===' - ; - -comparisonOperator - : '<' - | '>' - | '<=' - | '>=' - ; - -inOperator - : 'in' - | NOT_IN - ; - -isOperator - : 'is' - | NOT_IS - ; - -additiveOperator - : '+' - | '-' - ; - -multiplicativeOperator - : '*' - | '/' - | '%' - ; - -asOperator - : 'as' - | 'as?' - ; - -prefixUnaryOperator - : '++' - | '--' - | '-' - | '+' - | excl - ; - -postfixUnaryOperator - : '++' - | '--' - | EXCL_NO_WS excl - ; - -memberAccessOperator - : '.' - | safeNav - | '::' - ; - -modifiers - : (annotation | modifier)+ - ; - -modifier - : ( - classModifier - | memberModifier - | visibilityModifier - | functionModifier - | propertyModifier - | inheritanceModifier - | parameterModifier - | platformModifier - ) NL* - ; - -classModifier - : 'enum' - | 'sealed' - | 'annotation' - | 'data' - | 'inner' - ; - -memberModifier - : 'override' - | 'lateinit' - ; - -visibilityModifier - : 'public' - | 'private' - | 'internal' - | 'protected' - ; - -varianceModifier - : 'in' - | 'out' - ; - -functionModifier - : 'tailrec' - | 'operator' - | 'infix' - | 'inline' - | 'external' - | 'suspend' - ; - -propertyModifier - : 'const' - ; - -inheritanceModifier - : 'abstract' - | 'final' - | 'open' - ; - -parameterModifier - : 'vararg' - | 'noinline' - | 'crossinline' - ; - -reificationModifier - : 'reified' - ; - -platformModifier - : 'expect' - | 'actual' - ; - -label - : IdentifierAt NL* - ; - -annotation - : (singleAnnotation | multiAnnotation) NL* - ; - -singleAnnotation - : annotationUseSiteTarget NL* ':' NL* unescapedAnnotation - | '@' unescapedAnnotation - ; - -multiAnnotation - : annotationUseSiteTarget NL* ':' NL* '[' unescapedAnnotation+ ']' - | '@' '[' unescapedAnnotation+ ']' - ; - -annotationUseSiteTarget - : '@field' - | '@property' - | '@get' - | '@set' - | '@receiver' - | '@param' - | '@setparam' - | '@delegate' - ; - -unescapedAnnotation - : constructorInvocation - | userType - ; - -simpleIdentifier - : Identifier //soft keywords: - | 'abstract' - | 'annotation' - | 'by' - | 'catch' - | 'companion' - | 'constructor' - | 'crossinline' - | 'data' - | 'dynamic' - | 'enum' - | 'external' - | 'final' - | 'finally' - | 'get' - | 'import' - | 'infix' - | 'init' - | 'inline' - | 'inner' - | 'internal' - | 'lateinit' - | 'noinline' - | 'open' - | 'operator' - | 'out' - | 'override' - | 'private' - | 'protected' - | 'public' - | 'reified' - | 'sealed' - | 'tailrec' - | 'set' - | 'vararg' - | 'where' - | 'expect' - | 'actual' - | 'const' - | 'suspend' - ; - -identifier - : simpleIdentifier (NL* '.' simpleIdentifier)* - ; - -shebangLine - : ShebangLine NL+ - ; - -quest - : QUEST_NO_WS - | QUEST_WS - ; - -elvis - : QUEST_NO_WS ':' - ; - -safeNav - : QUEST_NO_WS '.' - ; - -excl - : EXCL_NO_WS - | EXCL_WS - ; - -semi - : (';' | NL) NL* // actually, it's WS or comment between ';', here it's handled in lexer (see ;; token) - | EOF - ; - -semis // writing this as "semi+" sends antlr into infinite loop or smth - : (';' | NL)+ - | EOF - ; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/UnicodeClasses.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/UnicodeClasses.g4 deleted file mode 100644 index 642a8b79..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/kotlin/UnicodeClasses.g4 +++ /dev/null @@ -1,1656 +0,0 @@ -/** - * Taken from http://www.antlr3.org/grammar/1345144569663/AntlrUnicode.txt - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar UnicodeClasses; - -UNICODE_CLASS_LL: - '\u0061' ..'\u007A' - | '\u00B5' - | '\u00DF' ..'\u00F6' - | '\u00F8' ..'\u00FF' - | '\u0101' - | '\u0103' - | '\u0105' - | '\u0107' - | '\u0109' - | '\u010B' - | '\u010D' - | '\u010F' - | '\u0111' - | '\u0113' - | '\u0115' - | '\u0117' - | '\u0119' - | '\u011B' - | '\u011D' - | '\u011F' - | '\u0121' - | '\u0123' - | '\u0125' - | '\u0127' - | '\u0129' - | '\u012B' - | '\u012D' - | '\u012F' - | '\u0131' - | '\u0133' - | '\u0135' - | '\u0137' - | '\u0138' - | '\u013A' - | '\u013C' - | '\u013E' - | '\u0140' - | '\u0142' - | '\u0144' - | '\u0146' - | '\u0148' - | '\u0149' - | '\u014B' - | '\u014D' - | '\u014F' - | '\u0151' - | '\u0153' - | '\u0155' - | '\u0157' - | '\u0159' - | '\u015B' - | '\u015D' - | '\u015F' - | '\u0161' - | '\u0163' - | '\u0165' - | '\u0167' - | '\u0169' - | '\u016B' - | '\u016D' - | '\u016F' - | '\u0171' - | '\u0173' - | '\u0175' - | '\u0177' - | '\u017A' - | '\u017C' - | '\u017E' ..'\u0180' - | '\u0183' - | '\u0185' - | '\u0188' - | '\u018C' - | '\u018D' - | '\u0192' - | '\u0195' - | '\u0199' ..'\u019B' - | '\u019E' - | '\u01A1' - | '\u01A3' - | '\u01A5' - | '\u01A8' - | '\u01AA' - | '\u01AB' - | '\u01AD' - | '\u01B0' - | '\u01B4' - | '\u01B6' - | '\u01B9' - | '\u01BA' - | '\u01BD' ..'\u01BF' - | '\u01C6' - | '\u01C9' - | '\u01CC' - | '\u01CE' - | '\u01D0' - | '\u01D2' - | '\u01D4' - | '\u01D6' - | '\u01D8' - | '\u01DA' - | '\u01DC' - | '\u01DD' - | '\u01DF' - | '\u01E1' - | '\u01E3' - | '\u01E5' - | '\u01E7' - | '\u01E9' - | '\u01EB' - | '\u01ED' - | '\u01EF' - | '\u01F0' - | '\u01F3' - | '\u01F5' - | '\u01F9' - | '\u01FB' - | '\u01FD' - | '\u01FF' - | '\u0201' - | '\u0203' - | '\u0205' - | '\u0207' - | '\u0209' - | '\u020B' - | '\u020D' - | '\u020F' - | '\u0211' - | '\u0213' - | '\u0215' - | '\u0217' - | '\u0219' - | '\u021B' - | '\u021D' - | '\u021F' - | '\u0221' - | '\u0223' - | '\u0225' - | '\u0227' - | '\u0229' - | '\u022B' - | '\u022D' - | '\u022F' - | '\u0231' - | '\u0233' ..'\u0239' - | '\u023C' - | '\u023F' - | '\u0240' - | '\u0242' - | '\u0247' - | '\u0249' - | '\u024B' - | '\u024D' - | '\u024F' ..'\u0293' - | '\u0295' ..'\u02AF' - | '\u0371' - | '\u0373' - | '\u0377' - | '\u037B' ..'\u037D' - | '\u0390' - | '\u03AC' ..'\u03CE' - | '\u03D0' - | '\u03D1' - | '\u03D5' ..'\u03D7' - | '\u03D9' - | '\u03DB' - | '\u03DD' - | '\u03DF' - | '\u03E1' - | '\u03E3' - | '\u03E5' - | '\u03E7' - | '\u03E9' - | '\u03EB' - | '\u03ED' - | '\u03EF' ..'\u03F3' - | '\u03F5' - | '\u03F8' - | '\u03FB' - | '\u03FC' - | '\u0430' ..'\u045F' - | '\u0461' - | '\u0463' - | '\u0465' - | '\u0467' - | '\u0469' - | '\u046B' - | '\u046D' - | '\u046F' - | '\u0471' - | '\u0473' - | '\u0475' - | '\u0477' - | '\u0479' - | '\u047B' - | '\u047D' - | '\u047F' - | '\u0481' - | '\u048B' - | '\u048D' - | '\u048F' - | '\u0491' - | '\u0493' - | '\u0495' - | '\u0497' - | '\u0499' - | '\u049B' - | '\u049D' - | '\u049F' - | '\u04A1' - | '\u04A3' - | '\u04A5' - | '\u04A7' - | '\u04A9' - | '\u04AB' - | '\u04AD' - | '\u04AF' - | '\u04B1' - | '\u04B3' - | '\u04B5' - | '\u04B7' - | '\u04B9' - | '\u04BB' - | '\u04BD' - | '\u04BF' - | '\u04C2' - | '\u04C4' - | '\u04C6' - | '\u04C8' - | '\u04CA' - | '\u04CC' - | '\u04CE' - | '\u04CF' - | '\u04D1' - | '\u04D3' - | '\u04D5' - | '\u04D7' - | '\u04D9' - | '\u04DB' - | '\u04DD' - | '\u04DF' - | '\u04E1' - | '\u04E3' - | '\u04E5' - | '\u04E7' - | '\u04E9' - | '\u04EB' - | '\u04ED' - | '\u04EF' - | '\u04F1' - | '\u04F3' - | '\u04F5' - | '\u04F7' - | '\u04F9' - | '\u04FB' - | '\u04FD' - | '\u04FF' - | '\u0501' - | '\u0503' - | '\u0505' - | '\u0507' - | '\u0509' - | '\u050B' - | '\u050D' - | '\u050F' - | '\u0511' - | '\u0513' - | '\u0515' - | '\u0517' - | '\u0519' - | '\u051B' - | '\u051D' - | '\u051F' - | '\u0521' - | '\u0523' - | '\u0525' - | '\u0527' - | '\u0561' ..'\u0587' - | '\u1D00' ..'\u1D2B' - | '\u1D6B' ..'\u1D77' - | '\u1D79' ..'\u1D9A' - | '\u1E01' - | '\u1E03' - | '\u1E05' - | '\u1E07' - | '\u1E09' - | '\u1E0B' - | '\u1E0D' - | '\u1E0F' - | '\u1E11' - | '\u1E13' - | '\u1E15' - | '\u1E17' - | '\u1E19' - | '\u1E1B' - | '\u1E1D' - | '\u1E1F' - | '\u1E21' - | '\u1E23' - | '\u1E25' - | '\u1E27' - | '\u1E29' - | '\u1E2B' - | '\u1E2D' - | '\u1E2F' - | '\u1E31' - | '\u1E33' - | '\u1E35' - | '\u1E37' - | '\u1E39' - | '\u1E3B' - | '\u1E3D' - | '\u1E3F' - | '\u1E41' - | '\u1E43' - | '\u1E45' - | '\u1E47' - | '\u1E49' - | '\u1E4B' - | '\u1E4D' - | '\u1E4F' - | '\u1E51' - | '\u1E53' - | '\u1E55' - | '\u1E57' - | '\u1E59' - | '\u1E5B' - | '\u1E5D' - | '\u1E5F' - | '\u1E61' - | '\u1E63' - | '\u1E65' - | '\u1E67' - | '\u1E69' - | '\u1E6B' - | '\u1E6D' - | '\u1E6F' - | '\u1E71' - | '\u1E73' - | '\u1E75' - | '\u1E77' - | '\u1E79' - | '\u1E7B' - | '\u1E7D' - | '\u1E7F' - | '\u1E81' - | '\u1E83' - | '\u1E85' - | '\u1E87' - | '\u1E89' - | '\u1E8B' - | '\u1E8D' - | '\u1E8F' - | '\u1E91' - | '\u1E93' - | '\u1E95' ..'\u1E9D' - | '\u1E9F' - | '\u1EA1' - | '\u1EA3' - | '\u1EA5' - | '\u1EA7' - | '\u1EA9' - | '\u1EAB' - | '\u1EAD' - | '\u1EAF' - | '\u1EB1' - | '\u1EB3' - | '\u1EB5' - | '\u1EB7' - | '\u1EB9' - | '\u1EBB' - | '\u1EBD' - | '\u1EBF' - | '\u1EC1' - | '\u1EC3' - | '\u1EC5' - | '\u1EC7' - | '\u1EC9' - | '\u1ECB' - | '\u1ECD' - | '\u1ECF' - | '\u1ED1' - | '\u1ED3' - | '\u1ED5' - | '\u1ED7' - | '\u1ED9' - | '\u1EDB' - | '\u1EDD' - | '\u1EDF' - | '\u1EE1' - | '\u1EE3' - | '\u1EE5' - | '\u1EE7' - | '\u1EE9' - | '\u1EEB' - | '\u1EED' - | '\u1EEF' - | '\u1EF1' - | '\u1EF3' - | '\u1EF5' - | '\u1EF7' - | '\u1EF9' - | '\u1EFB' - | '\u1EFD' - | '\u1EFF' ..'\u1F07' - | '\u1F10' ..'\u1F15' - | '\u1F20' ..'\u1F27' - | '\u1F30' ..'\u1F37' - | '\u1F40' ..'\u1F45' - | '\u1F50' ..'\u1F57' - | '\u1F60' ..'\u1F67' - | '\u1F70' ..'\u1F7D' - | '\u1F80' ..'\u1F87' - | '\u1F90' ..'\u1F97' - | '\u1FA0' ..'\u1FA7' - | '\u1FB0' ..'\u1FB4' - | '\u1FB6' - | '\u1FB7' - | '\u1FBE' - | '\u1FC2' ..'\u1FC4' - | '\u1FC6' - | '\u1FC7' - | '\u1FD0' ..'\u1FD3' - | '\u1FD6' - | '\u1FD7' - | '\u1FE0' ..'\u1FE7' - | '\u1FF2' ..'\u1FF4' - | '\u1FF6' - | '\u1FF7' - | '\u210A' - | '\u210E' - | '\u210F' - | '\u2113' - | '\u212F' - | '\u2134' - | '\u2139' - | '\u213C' - | '\u213D' - | '\u2146' ..'\u2149' - | '\u214E' - | '\u2184' - | '\u2C30' ..'\u2C5E' - | '\u2C61' - | '\u2C65' - | '\u2C66' - | '\u2C68' - | '\u2C6A' - | '\u2C6C' - | '\u2C71' - | '\u2C73' - | '\u2C74' - | '\u2C76' ..'\u2C7B' - | '\u2C81' - | '\u2C83' - | '\u2C85' - | '\u2C87' - | '\u2C89' - | '\u2C8B' - | '\u2C8D' - | '\u2C8F' - | '\u2C91' - | '\u2C93' - | '\u2C95' - | '\u2C97' - | '\u2C99' - | '\u2C9B' - | '\u2C9D' - | '\u2C9F' - | '\u2CA1' - | '\u2CA3' - | '\u2CA5' - | '\u2CA7' - | '\u2CA9' - | '\u2CAB' - | '\u2CAD' - | '\u2CAF' - | '\u2CB1' - | '\u2CB3' - | '\u2CB5' - | '\u2CB7' - | '\u2CB9' - | '\u2CBB' - | '\u2CBD' - | '\u2CBF' - | '\u2CC1' - | '\u2CC3' - | '\u2CC5' - | '\u2CC7' - | '\u2CC9' - | '\u2CCB' - | '\u2CCD' - | '\u2CCF' - | '\u2CD1' - | '\u2CD3' - | '\u2CD5' - | '\u2CD7' - | '\u2CD9' - | '\u2CDB' - | '\u2CDD' - | '\u2CDF' - | '\u2CE1' - | '\u2CE3' - | '\u2CE4' - | '\u2CEC' - | '\u2CEE' - | '\u2CF3' - | '\u2D00' ..'\u2D25' - | '\u2D27' - | '\u2D2D' - | '\uA641' - | '\uA643' - | '\uA645' - | '\uA647' - | '\uA649' - | '\uA64B' - | '\uA64D' - | '\uA64F' - | '\uA651' - | '\uA653' - | '\uA655' - | '\uA657' - | '\uA659' - | '\uA65B' - | '\uA65D' - | '\uA65F' - | '\uA661' - | '\uA663' - | '\uA665' - | '\uA667' - | '\uA669' - | '\uA66B' - | '\uA66D' - | '\uA681' - | '\uA683' - | '\uA685' - | '\uA687' - | '\uA689' - | '\uA68B' - | '\uA68D' - | '\uA68F' - | '\uA691' - | '\uA693' - | '\uA695' - | '\uA697' - | '\uA723' - | '\uA725' - | '\uA727' - | '\uA729' - | '\uA72B' - | '\uA72D' - | '\uA72F' ..'\uA731' - | '\uA733' - | '\uA735' - | '\uA737' - | '\uA739' - | '\uA73B' - | '\uA73D' - | '\uA73F' - | '\uA741' - | '\uA743' - | '\uA745' - | '\uA747' - | '\uA749' - | '\uA74B' - | '\uA74D' - | '\uA74F' - | '\uA751' - | '\uA753' - | '\uA755' - | '\uA757' - | '\uA759' - | '\uA75B' - | '\uA75D' - | '\uA75F' - | '\uA761' - | '\uA763' - | '\uA765' - | '\uA767' - | '\uA769' - | '\uA76B' - | '\uA76D' - | '\uA76F' - | '\uA771' ..'\uA778' - | '\uA77A' - | '\uA77C' - | '\uA77F' - | '\uA781' - | '\uA783' - | '\uA785' - | '\uA787' - | '\uA78C' - | '\uA78E' - | '\uA791' - | '\uA793' - | '\uA7A1' - | '\uA7A3' - | '\uA7A5' - | '\uA7A7' - | '\uA7A9' - | '\uA7FA' - | '\uFB00' ..'\uFB06' - | '\uFB13' ..'\uFB17' - | '\uFF41' ..'\uFF5A' -; - -UNICODE_CLASS_LM: - '\u02B0' ..'\u02C1' - | '\u02C6' ..'\u02D1' - | '\u02E0' ..'\u02E4' - | '\u02EC' - | '\u02EE' - | '\u0374' - | '\u037A' - | '\u0559' - | '\u0640' - | '\u06E5' - | '\u06E6' - | '\u07F4' - | '\u07F5' - | '\u07FA' - | '\u081A' - | '\u0824' - | '\u0828' - | '\u0971' - | '\u0E46' - | '\u0EC6' - | '\u10FC' - | '\u17D7' - | '\u1843' - | '\u1AA7' - | '\u1C78' ..'\u1C7D' - | '\u1D2C' ..'\u1D6A' - | '\u1D78' - | '\u1D9B' ..'\u1DBF' - | '\u2071' - | '\u207F' - | '\u2090' ..'\u209C' - | '\u2C7C' - | '\u2C7D' - | '\u2D6F' - | '\u2E2F' - | '\u3005' - | '\u3031' ..'\u3035' - | '\u303B' - | '\u309D' - | '\u309E' - | '\u30FC' ..'\u30FE' - | '\uA015' - | '\uA4F8' ..'\uA4FD' - | '\uA60C' - | '\uA67F' - | '\uA717' ..'\uA71F' - | '\uA770' - | '\uA788' - | '\uA7F8' - | '\uA7F9' - | '\uA9CF' - | '\uAA70' - | '\uAADD' - | '\uAAF3' - | '\uAAF4' - | '\uFF70' - | '\uFF9E' - | '\uFF9F' -; - -UNICODE_CLASS_LO: - '\u00AA' - | '\u00BA' - | '\u01BB' - | '\u01C0' ..'\u01C3' - | '\u0294' - | '\u05D0' ..'\u05EA' - | '\u05F0' ..'\u05F2' - | '\u0620' ..'\u063F' - | '\u0641' ..'\u064A' - | '\u066E' - | '\u066F' - | '\u0671' ..'\u06D3' - | '\u06D5' - | '\u06EE' - | '\u06EF' - | '\u06FA' ..'\u06FC' - | '\u06FF' - | '\u0710' - | '\u0712' ..'\u072F' - | '\u074D' ..'\u07A5' - | '\u07B1' - | '\u07CA' ..'\u07EA' - | '\u0800' ..'\u0815' - | '\u0840' ..'\u0858' - | '\u08A0' - | '\u08A2' ..'\u08AC' - | '\u0904' ..'\u0939' - | '\u093D' - | '\u0950' - | '\u0958' ..'\u0961' - | '\u0972' ..'\u0977' - | '\u0979' ..'\u097F' - | '\u0985' ..'\u098C' - | '\u098F' - | '\u0990' - | '\u0993' ..'\u09A8' - | '\u09AA' ..'\u09B0' - | '\u09B2' - | '\u09B6' ..'\u09B9' - | '\u09BD' - | '\u09CE' - | '\u09DC' - | '\u09DD' - | '\u09DF' ..'\u09E1' - | '\u09F0' - | '\u09F1' - | '\u0A05' ..'\u0A0A' - | '\u0A0F' - | '\u0A10' - | '\u0A13' ..'\u0A28' - | '\u0A2A' ..'\u0A30' - | '\u0A32' - | '\u0A33' - | '\u0A35' - | '\u0A36' - | '\u0A38' - | '\u0A39' - | '\u0A59' ..'\u0A5C' - | '\u0A5E' - | '\u0A72' ..'\u0A74' - | '\u0A85' ..'\u0A8D' - | '\u0A8F' ..'\u0A91' - | '\u0A93' ..'\u0AA8' - | '\u0AAA' ..'\u0AB0' - | '\u0AB2' - | '\u0AB3' - | '\u0AB5' ..'\u0AB9' - | '\u0ABD' - | '\u0AD0' - | '\u0AE0' - | '\u0AE1' - | '\u0B05' ..'\u0B0C' - | '\u0B0F' - | '\u0B10' - | '\u0B13' ..'\u0B28' - | '\u0B2A' ..'\u0B30' - | '\u0B32' - | '\u0B33' - | '\u0B35' ..'\u0B39' - | '\u0B3D' - | '\u0B5C' - | '\u0B5D' - | '\u0B5F' ..'\u0B61' - | '\u0B71' - | '\u0B83' - | '\u0B85' ..'\u0B8A' - | '\u0B8E' ..'\u0B90' - | '\u0B92' ..'\u0B95' - | '\u0B99' - | '\u0B9A' - | '\u0B9C' - | '\u0B9E' - | '\u0B9F' - | '\u0BA3' - | '\u0BA4' - | '\u0BA8' ..'\u0BAA' - | '\u0BAE' ..'\u0BB9' - | '\u0BD0' - | '\u0C05' ..'\u0C0C' - | '\u0C0E' ..'\u0C10' - | '\u0C12' ..'\u0C28' - | '\u0C2A' ..'\u0C33' - | '\u0C35' ..'\u0C39' - | '\u0C3D' - | '\u0C58' - | '\u0C59' - | '\u0C60' - | '\u0C61' - | '\u0C85' ..'\u0C8C' - | '\u0C8E' ..'\u0C90' - | '\u0C92' ..'\u0CA8' - | '\u0CAA' ..'\u0CB3' - | '\u0CB5' ..'\u0CB9' - | '\u0CBD' - | '\u0CDE' - | '\u0CE0' - | '\u0CE1' - | '\u0CF1' - | '\u0CF2' - | '\u0D05' ..'\u0D0C' - | '\u0D0E' ..'\u0D10' - | '\u0D12' ..'\u0D3A' - | '\u0D3D' - | '\u0D4E' - | '\u0D60' - | '\u0D61' - | '\u0D7A' ..'\u0D7F' - | '\u0D85' ..'\u0D96' - | '\u0D9A' ..'\u0DB1' - | '\u0DB3' ..'\u0DBB' - | '\u0DBD' - | '\u0DC0' ..'\u0DC6' - | '\u0E01' ..'\u0E30' - | '\u0E32' - | '\u0E33' - | '\u0E40' ..'\u0E45' - | '\u0E81' - | '\u0E82' - | '\u0E84' - | '\u0E87' - | '\u0E88' - | '\u0E8A' - | '\u0E8D' - | '\u0E94' ..'\u0E97' - | '\u0E99' ..'\u0E9F' - | '\u0EA1' ..'\u0EA3' - | '\u0EA5' - | '\u0EA7' - | '\u0EAA' - | '\u0EAB' - | '\u0EAD' ..'\u0EB0' - | '\u0EB2' - | '\u0EB3' - | '\u0EBD' - | '\u0EC0' ..'\u0EC4' - | '\u0EDC' ..'\u0EDF' - | '\u0F00' - | '\u0F40' ..'\u0F47' - | '\u0F49' ..'\u0F6C' - | '\u0F88' ..'\u0F8C' - | '\u1000' ..'\u102A' - | '\u103F' - | '\u1050' ..'\u1055' - | '\u105A' ..'\u105D' - | '\u1061' - | '\u1065' - | '\u1066' - | '\u106E' ..'\u1070' - | '\u1075' ..'\u1081' - | '\u108E' - | '\u10D0' ..'\u10FA' - | '\u10FD' ..'\u1248' - | '\u124A' ..'\u124D' - | '\u1250' ..'\u1256' - | '\u1258' - | '\u125A' ..'\u125D' - | '\u1260' ..'\u1288' - | '\u128A' ..'\u128D' - | '\u1290' ..'\u12B0' - | '\u12B2' ..'\u12B5' - | '\u12B8' ..'\u12BE' - | '\u12C0' - | '\u12C2' ..'\u12C5' - | '\u12C8' ..'\u12D6' - | '\u12D8' ..'\u1310' - | '\u1312' ..'\u1315' - | '\u1318' ..'\u135A' - | '\u1380' ..'\u138F' - | '\u13A0' ..'\u13F4' - | '\u1401' ..'\u166C' - | '\u166F' ..'\u167F' - | '\u1681' ..'\u169A' - | '\u16A0' ..'\u16EA' - | '\u1700' ..'\u170C' - | '\u170E' ..'\u1711' - | '\u1720' ..'\u1731' - | '\u1740' ..'\u1751' - | '\u1760' ..'\u176C' - | '\u176E' ..'\u1770' - | '\u1780' ..'\u17B3' - | '\u17DC' - | '\u1820' ..'\u1842' - | '\u1844' ..'\u1877' - | '\u1880' ..'\u18A8' - | '\u18AA' - | '\u18B0' ..'\u18F5' - | '\u1900' ..'\u191C' - | '\u1950' ..'\u196D' - | '\u1970' ..'\u1974' - | '\u1980' ..'\u19AB' - | '\u19C1' ..'\u19C7' - | '\u1A00' ..'\u1A16' - | '\u1A20' ..'\u1A54' - | '\u1B05' ..'\u1B33' - | '\u1B45' ..'\u1B4B' - | '\u1B83' ..'\u1BA0' - | '\u1BAE' - | '\u1BAF' - | '\u1BBA' ..'\u1BE5' - | '\u1C00' ..'\u1C23' - | '\u1C4D' ..'\u1C4F' - | '\u1C5A' ..'\u1C77' - | '\u1CE9' ..'\u1CEC' - | '\u1CEE' ..'\u1CF1' - | '\u1CF5' - | '\u1CF6' - | '\u2135' ..'\u2138' - | '\u2D30' ..'\u2D67' - | '\u2D80' ..'\u2D96' - | '\u2DA0' ..'\u2DA6' - | '\u2DA8' ..'\u2DAE' - | '\u2DB0' ..'\u2DB6' - | '\u2DB8' ..'\u2DBE' - | '\u2DC0' ..'\u2DC6' - | '\u2DC8' ..'\u2DCE' - | '\u2DD0' ..'\u2DD6' - | '\u2DD8' ..'\u2DDE' - | '\u3006' - | '\u303C' - | '\u3041' ..'\u3096' - | '\u309F' - | '\u30A1' ..'\u30FA' - | '\u30FF' - | '\u3105' ..'\u312D' - | '\u3131' ..'\u318E' - | '\u31A0' ..'\u31BA' - | '\u31F0' ..'\u31FF' - | '\u3400' ..'\u4DB5' - | '\u4E00' ..'\u9FCC' - | '\uA000' ..'\uA014' - | '\uA016' ..'\uA48C' - | '\uA4D0' ..'\uA4F7' - | '\uA500' ..'\uA60B' - | '\uA610' ..'\uA61F' - | '\uA62A' - | '\uA62B' - | '\uA66E' - | '\uA6A0' ..'\uA6E5' - | '\uA7FB' ..'\uA801' - | '\uA803' ..'\uA805' - | '\uA807' ..'\uA80A' - | '\uA80C' ..'\uA822' - | '\uA840' ..'\uA873' - | '\uA882' ..'\uA8B3' - | '\uA8F2' ..'\uA8F7' - | '\uA8FB' - | '\uA90A' ..'\uA925' - | '\uA930' ..'\uA946' - | '\uA960' ..'\uA97C' - | '\uA984' ..'\uA9B2' - | '\uAA00' ..'\uAA28' - | '\uAA40' ..'\uAA42' - | '\uAA44' ..'\uAA4B' - | '\uAA60' ..'\uAA6F' - | '\uAA71' ..'\uAA76' - | '\uAA7A' - | '\uAA80' ..'\uAAAF' - | '\uAAB1' - | '\uAAB5' - | '\uAAB6' - | '\uAAB9' ..'\uAABD' - | '\uAAC0' - | '\uAAC2' - | '\uAADB' - | '\uAADC' - | '\uAAE0' ..'\uAAEA' - | '\uAAF2' - | '\uAB01' ..'\uAB06' - | '\uAB09' ..'\uAB0E' - | '\uAB11' ..'\uAB16' - | '\uAB20' ..'\uAB26' - | '\uAB28' ..'\uAB2E' - | '\uABC0' ..'\uABE2' - | '\uAC00' - | '\uD7A3' - | '\uD7B0' ..'\uD7C6' - | '\uD7CB' ..'\uD7FB' - | '\uF900' ..'\uFA6D' - | '\uFA70' ..'\uFAD9' - | '\uFB1D' - | '\uFB1F' ..'\uFB28' - | '\uFB2A' ..'\uFB36' - | '\uFB38' ..'\uFB3C' - | '\uFB3E' - | '\uFB40' - | '\uFB41' - | '\uFB43' - | '\uFB44' - | '\uFB46' ..'\uFBB1' - | '\uFBD3' ..'\uFD3D' - | '\uFD50' ..'\uFD8F' - | '\uFD92' ..'\uFDC7' - | '\uFDF0' ..'\uFDFB' - | '\uFE70' ..'\uFE74' - | '\uFE76' ..'\uFEFC' - | '\uFF66' ..'\uFF6F' - | '\uFF71' ..'\uFF9D' - | '\uFFA0' ..'\uFFBE' - | '\uFFC2' ..'\uFFC7' - | '\uFFCA' ..'\uFFCF' - | '\uFFD2' ..'\uFFD7' - | '\uFFDA' ..'\uFFDC' -; - -UNICODE_CLASS_LT: - '\u01C5' - | '\u01C8' - | '\u01CB' - | '\u01F2' - | '\u1F88' ..'\u1F8F' - | '\u1F98' ..'\u1F9F' - | '\u1FA8' ..'\u1FAF' - | '\u1FBC' - | '\u1FCC' - | '\u1FFC' -; - -UNICODE_CLASS_LU: - '\u0041' ..'\u005A' - | '\u00C0' ..'\u00D6' - | '\u00D8' ..'\u00DE' - | '\u0100' - | '\u0102' - | '\u0104' - | '\u0106' - | '\u0108' - | '\u010A' - | '\u010C' - | '\u010E' - | '\u0110' - | '\u0112' - | '\u0114' - | '\u0116' - | '\u0118' - | '\u011A' - | '\u011C' - | '\u011E' - | '\u0120' - | '\u0122' - | '\u0124' - | '\u0126' - | '\u0128' - | '\u012A' - | '\u012C' - | '\u012E' - | '\u0130' - | '\u0132' - | '\u0134' - | '\u0136' - | '\u0139' - | '\u013B' - | '\u013D' - | '\u013F' - | '\u0141' - | '\u0143' - | '\u0145' - | '\u0147' - | '\u014A' - | '\u014C' - | '\u014E' - | '\u0150' - | '\u0152' - | '\u0154' - | '\u0156' - | '\u0158' - | '\u015A' - | '\u015C' - | '\u015E' - | '\u0160' - | '\u0162' - | '\u0164' - | '\u0166' - | '\u0168' - | '\u016A' - | '\u016C' - | '\u016E' - | '\u0170' - | '\u0172' - | '\u0174' - | '\u0176' - | '\u0178' - | '\u0179' - | '\u017B' - | '\u017D' - | '\u0181' - | '\u0182' - | '\u0184' - | '\u0186' - | '\u0187' - | '\u0189' ..'\u018B' - | '\u018E' ..'\u0191' - | '\u0193' - | '\u0194' - | '\u0196' ..'\u0198' - | '\u019C' - | '\u019D' - | '\u019F' - | '\u01A0' - | '\u01A2' - | '\u01A4' - | '\u01A6' - | '\u01A7' - | '\u01A9' - | '\u01AC' - | '\u01AE' - | '\u01AF' - | '\u01B1' ..'\u01B3' - | '\u01B5' - | '\u01B7' - | '\u01B8' - | '\u01BC' - | '\u01C4' - | '\u01C7' - | '\u01CA' - | '\u01CD' - | '\u01CF' - | '\u01D1' - | '\u01D3' - | '\u01D5' - | '\u01D7' - | '\u01D9' - | '\u01DB' - | '\u01DE' - | '\u01E0' - | '\u01E2' - | '\u01E4' - | '\u01E6' - | '\u01E8' - | '\u01EA' - | '\u01EC' - | '\u01EE' - | '\u01F1' - | '\u01F4' - | '\u01F6' ..'\u01F8' - | '\u01FA' - | '\u01FC' - | '\u01FE' - | '\u0200' - | '\u0202' - | '\u0204' - | '\u0206' - | '\u0208' - | '\u020A' - | '\u020C' - | '\u020E' - | '\u0210' - | '\u0212' - | '\u0214' - | '\u0216' - | '\u0218' - | '\u021A' - | '\u021C' - | '\u021E' - | '\u0220' - | '\u0222' - | '\u0224' - | '\u0226' - | '\u0228' - | '\u022A' - | '\u022C' - | '\u022E' - | '\u0230' - | '\u0232' - | '\u023A' - | '\u023B' - | '\u023D' - | '\u023E' - | '\u0241' - | '\u0243' ..'\u0246' - | '\u0248' - | '\u024A' - | '\u024C' - | '\u024E' - | '\u0370' - | '\u0372' - | '\u0376' - | '\u0386' - | '\u0388' ..'\u038A' - | '\u038C' - | '\u038E' - | '\u038F' - | '\u0391' ..'\u03A1' - | '\u03A3' ..'\u03AB' - | '\u03CF' - | '\u03D2' ..'\u03D4' - | '\u03D8' - | '\u03DA' - | '\u03DC' - | '\u03DE' - | '\u03E0' - | '\u03E2' - | '\u03E4' - | '\u03E6' - | '\u03E8' - | '\u03EA' - | '\u03EC' - | '\u03EE' - | '\u03F4' - | '\u03F7' - | '\u03F9' - | '\u03FA' - | '\u03FD' ..'\u042F' - | '\u0460' - | '\u0462' - | '\u0464' - | '\u0466' - | '\u0468' - | '\u046A' - | '\u046C' - | '\u046E' - | '\u0470' - | '\u0472' - | '\u0474' - | '\u0476' - | '\u0478' - | '\u047A' - | '\u047C' - | '\u047E' - | '\u0480' - | '\u048A' - | '\u048C' - | '\u048E' - | '\u0490' - | '\u0492' - | '\u0494' - | '\u0496' - | '\u0498' - | '\u049A' - | '\u049C' - | '\u049E' - | '\u04A0' - | '\u04A2' - | '\u04A4' - | '\u04A6' - | '\u04A8' - | '\u04AA' - | '\u04AC' - | '\u04AE' - | '\u04B0' - | '\u04B2' - | '\u04B4' - | '\u04B6' - | '\u04B8' - | '\u04BA' - | '\u04BC' - | '\u04BE' - | '\u04C0' - | '\u04C1' - | '\u04C3' - | '\u04C5' - | '\u04C7' - | '\u04C9' - | '\u04CB' - | '\u04CD' - | '\u04D0' - | '\u04D2' - | '\u04D4' - | '\u04D6' - | '\u04D8' - | '\u04DA' - | '\u04DC' - | '\u04DE' - | '\u04E0' - | '\u04E2' - | '\u04E4' - | '\u04E6' - | '\u04E8' - | '\u04EA' - | '\u04EC' - | '\u04EE' - | '\u04F0' - | '\u04F2' - | '\u04F4' - | '\u04F6' - | '\u04F8' - | '\u04FA' - | '\u04FC' - | '\u04FE' - | '\u0500' - | '\u0502' - | '\u0504' - | '\u0506' - | '\u0508' - | '\u050A' - | '\u050C' - | '\u050E' - | '\u0510' - | '\u0512' - | '\u0514' - | '\u0516' - | '\u0518' - | '\u051A' - | '\u051C' - | '\u051E' - | '\u0520' - | '\u0522' - | '\u0524' - | '\u0526' - | '\u0531' ..'\u0556' - | '\u10A0' ..'\u10C5' - | '\u10C7' - | '\u10CD' - | '\u1E00' - | '\u1E02' - | '\u1E04' - | '\u1E06' - | '\u1E08' - | '\u1E0A' - | '\u1E0C' - | '\u1E0E' - | '\u1E10' - | '\u1E12' - | '\u1E14' - | '\u1E16' - | '\u1E18' - | '\u1E1A' - | '\u1E1C' - | '\u1E1E' - | '\u1E20' - | '\u1E22' - | '\u1E24' - | '\u1E26' - | '\u1E28' - | '\u1E2A' - | '\u1E2C' - | '\u1E2E' - | '\u1E30' - | '\u1E32' - | '\u1E34' - | '\u1E36' - | '\u1E38' - | '\u1E3A' - | '\u1E3C' - | '\u1E3E' - | '\u1E40' - | '\u1E42' - | '\u1E44' - | '\u1E46' - | '\u1E48' - | '\u1E4A' - | '\u1E4C' - | '\u1E4E' - | '\u1E50' - | '\u1E52' - | '\u1E54' - | '\u1E56' - | '\u1E58' - | '\u1E5A' - | '\u1E5C' - | '\u1E5E' - | '\u1E60' - | '\u1E62' - | '\u1E64' - | '\u1E66' - | '\u1E68' - | '\u1E6A' - | '\u1E6C' - | '\u1E6E' - | '\u1E70' - | '\u1E72' - | '\u1E74' - | '\u1E76' - | '\u1E78' - | '\u1E7A' - | '\u1E7C' - | '\u1E7E' - | '\u1E80' - | '\u1E82' - | '\u1E84' - | '\u1E86' - | '\u1E88' - | '\u1E8A' - | '\u1E8C' - | '\u1E8E' - | '\u1E90' - | '\u1E92' - | '\u1E94' - | '\u1E9E' - | '\u1EA0' - | '\u1EA2' - | '\u1EA4' - | '\u1EA6' - | '\u1EA8' - | '\u1EAA' - | '\u1EAC' - | '\u1EAE' - | '\u1EB0' - | '\u1EB2' - | '\u1EB4' - | '\u1EB6' - | '\u1EB8' - | '\u1EBA' - | '\u1EBC' - | '\u1EBE' - | '\u1EC0' - | '\u1EC2' - | '\u1EC4' - | '\u1EC6' - | '\u1EC8' - | '\u1ECA' - | '\u1ECC' - | '\u1ECE' - | '\u1ED0' - | '\u1ED2' - | '\u1ED4' - | '\u1ED6' - | '\u1ED8' - | '\u1EDA' - | '\u1EDC' - | '\u1EDE' - | '\u1EE0' - | '\u1EE2' - | '\u1EE4' - | '\u1EE6' - | '\u1EE8' - | '\u1EEA' - | '\u1EEC' - | '\u1EEE' - | '\u1EF0' - | '\u1EF2' - | '\u1EF4' - | '\u1EF6' - | '\u1EF8' - | '\u1EFA' - | '\u1EFC' - | '\u1EFE' - | '\u1F08' ..'\u1F0F' - | '\u1F18' ..'\u1F1D' - | '\u1F28' ..'\u1F2F' - | '\u1F38' ..'\u1F3F' - | '\u1F48' ..'\u1F4D' - | '\u1F59' - | '\u1F5B' - | '\u1F5D' - | '\u1F5F' - | '\u1F68' ..'\u1F6F' - | '\u1FB8' ..'\u1FBB' - | '\u1FC8' ..'\u1FCB' - | '\u1FD8' ..'\u1FDB' - | '\u1FE8' ..'\u1FEC' - | '\u1FF8' ..'\u1FFB' - | '\u2102' - | '\u2107' - | '\u210B' ..'\u210D' - | '\u2110' ..'\u2112' - | '\u2115' - | '\u2119' ..'\u211D' - | '\u2124' - | '\u2126' - | '\u2128' - | '\u212A' ..'\u212D' - | '\u2130' ..'\u2133' - | '\u213E' - | '\u213F' - | '\u2145' - | '\u2183' - | '\u2C00' ..'\u2C2E' - | '\u2C60' - | '\u2C62' ..'\u2C64' - | '\u2C67' - | '\u2C69' - | '\u2C6B' - | '\u2C6D' ..'\u2C70' - | '\u2C72' - | '\u2C75' - | '\u2C7E' ..'\u2C80' - | '\u2C82' - | '\u2C84' - | '\u2C86' - | '\u2C88' - | '\u2C8A' - | '\u2C8C' - | '\u2C8E' - | '\u2C90' - | '\u2C92' - | '\u2C94' - | '\u2C96' - | '\u2C98' - | '\u2C9A' - | '\u2C9C' - | '\u2C9E' - | '\u2CA0' - | '\u2CA2' - | '\u2CA4' - | '\u2CA6' - | '\u2CA8' - | '\u2CAA' - | '\u2CAC' - | '\u2CAE' - | '\u2CB0' - | '\u2CB2' - | '\u2CB4' - | '\u2CB6' - | '\u2CB8' - | '\u2CBA' - | '\u2CBC' - | '\u2CBE' - | '\u2CC0' - | '\u2CC2' - | '\u2CC4' - | '\u2CC6' - | '\u2CC8' - | '\u2CCA' - | '\u2CCC' - | '\u2CCE' - | '\u2CD0' - | '\u2CD2' - | '\u2CD4' - | '\u2CD6' - | '\u2CD8' - | '\u2CDA' - | '\u2CDC' - | '\u2CDE' - | '\u2CE0' - | '\u2CE2' - | '\u2CEB' - | '\u2CED' - | '\u2CF2' - | '\uA640' - | '\uA642' - | '\uA644' - | '\uA646' - | '\uA648' - | '\uA64A' - | '\uA64C' - | '\uA64E' - | '\uA650' - | '\uA652' - | '\uA654' - | '\uA656' - | '\uA658' - | '\uA65A' - | '\uA65C' - | '\uA65E' - | '\uA660' - | '\uA662' - | '\uA664' - | '\uA666' - | '\uA668' - | '\uA66A' - | '\uA66C' - | '\uA680' - | '\uA682' - | '\uA684' - | '\uA686' - | '\uA688' - | '\uA68A' - | '\uA68C' - | '\uA68E' - | '\uA690' - | '\uA692' - | '\uA694' - | '\uA696' - | '\uA722' - | '\uA724' - | '\uA726' - | '\uA728' - | '\uA72A' - | '\uA72C' - | '\uA72E' - | '\uA732' - | '\uA734' - | '\uA736' - | '\uA738' - | '\uA73A' - | '\uA73C' - | '\uA73E' - | '\uA740' - | '\uA742' - | '\uA744' - | '\uA746' - | '\uA748' - | '\uA74A' - | '\uA74C' - | '\uA74E' - | '\uA750' - | '\uA752' - | '\uA754' - | '\uA756' - | '\uA758' - | '\uA75A' - | '\uA75C' - | '\uA75E' - | '\uA760' - | '\uA762' - | '\uA764' - | '\uA766' - | '\uA768' - | '\uA76A' - | '\uA76C' - | '\uA76E' - | '\uA779' - | '\uA77B' - | '\uA77D' - | '\uA77E' - | '\uA780' - | '\uA782' - | '\uA784' - | '\uA786' - | '\uA78B' - | '\uA78D' - | '\uA790' - | '\uA792' - | '\uA7A0' - | '\uA7A2' - | '\uA7A4' - | '\uA7A6' - | '\uA7A8' - | '\uA7AA' - | '\uFF21' ..'\uFF3A' -; - -UNICODE_CLASS_ND: - '\u0030' ..'\u0039' - | '\u0660' ..'\u0669' - | '\u06F0' ..'\u06F9' - | '\u07C0' ..'\u07C9' - | '\u0966' ..'\u096F' - | '\u09E6' ..'\u09EF' - | '\u0A66' ..'\u0A6F' - | '\u0AE6' ..'\u0AEF' - | '\u0B66' ..'\u0B6F' - | '\u0BE6' ..'\u0BEF' - | '\u0C66' ..'\u0C6F' - | '\u0CE6' ..'\u0CEF' - | '\u0D66' ..'\u0D6F' - | '\u0E50' ..'\u0E59' - | '\u0ED0' ..'\u0ED9' - | '\u0F20' ..'\u0F29' - | '\u1040' ..'\u1049' - | '\u1090' ..'\u1099' - | '\u17E0' ..'\u17E9' - | '\u1810' ..'\u1819' - | '\u1946' ..'\u194F' - | '\u19D0' ..'\u19D9' - | '\u1A80' ..'\u1A89' - | '\u1A90' ..'\u1A99' - | '\u1B50' ..'\u1B59' - | '\u1BB0' ..'\u1BB9' - | '\u1C40' ..'\u1C49' - | '\u1C50' ..'\u1C59' - | '\uA620' ..'\uA629' - | '\uA8D0' ..'\uA8D9' - | '\uA900' ..'\uA909' - | '\uA9D0' ..'\uA9D9' - | '\uAA50' ..'\uAA59' - | '\uABF0' ..'\uABF9' - | '\uFF10' ..'\uFF19' -; - -UNICODE_CLASS_NL: - '\u16EE' ..'\u16F0' - | '\u2160' ..'\u2182' - | '\u2185' ..'\u2188' - | '\u3007' - | '\u3021' ..'\u3029' - | '\u3038' ..'\u303A' - | '\uA6E6' ..'\uA6EF' -; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Lexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Lexer.g4 deleted file mode 100644 index 8b36564b..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Lexer.g4 +++ /dev/null @@ -1,313 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Project : python3-parser; an ANTLR4 grammar for Python 3 - * https://github.com/bkiers/python3-parser - * Developed by : Bart Kiers, bart@big-o.nl - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar Python3Lexer; - -// All comments that start with "///" are copy-pasted from -// The Python Language Reference - -tokens { - INDENT, - DEDENT -} - -options { - superClass = Python3LexerBase; -} - -// Insert here @header for C++ lexer. - -/* - * lexer rules - */ - -STRING: STRING_LITERAL | BYTES_LITERAL; - -NUMBER: INTEGER | FLOAT_NUMBER | IMAG_NUMBER; - -INTEGER: DECIMAL_INTEGER | OCT_INTEGER | HEX_INTEGER | BIN_INTEGER; - -AND : 'and'; -AS : 'as'; -ASSERT : 'assert'; -ASYNC : 'async'; -AWAIT : 'await'; -BREAK : 'break'; -CASE : 'case'; -CLASS : 'class'; -CONTINUE : 'continue'; -DEF : 'def'; -DEL : 'del'; -ELIF : 'elif'; -ELSE : 'else'; -EXCEPT : 'except'; -FALSE : 'False'; -FINALLY : 'finally'; -FOR : 'for'; -FROM : 'from'; -GLOBAL : 'global'; -IF : 'if'; -IMPORT : 'import'; -IN : 'in'; -IS : 'is'; -LAMBDA : 'lambda'; -MATCH : 'match'; -NONE : 'None'; -NONLOCAL : 'nonlocal'; -NOT : 'not'; -OR : 'or'; -PASS : 'pass'; -RAISE : 'raise'; -RETURN : 'return'; -TRUE : 'True'; -TRY : 'try'; -UNDERSCORE : '_'; -WHILE : 'while'; -WITH : 'with'; -YIELD : 'yield'; - -NEWLINE: ({this.atStartOfInput()}? SPACES | ( '\r'? '\n' | '\r' | '\f') SPACES?) {this.onNewLine();}; - -/// identifier ::= id_start id_continue* -NAME: ID_START ID_CONTINUE*; - -/// stringliteral ::= [stringprefix](shortstring | longstring) -/// stringprefix ::= "r" | "u" | "R" | "U" | "f" | "F" -/// | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF" -STRING_LITERAL: ( [rR] | [uU] | [fF] | ( [fF] [rR]) | ( [rR] [fF]))? ( SHORT_STRING | LONG_STRING); - -/// bytesliteral ::= bytesprefix(shortbytes | longbytes) -/// bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" -BYTES_LITERAL: ( [bB] | ( [bB] [rR]) | ( [rR] [bB])) ( SHORT_BYTES | LONG_BYTES); - -/// decimalinteger ::= nonzerodigit digit* | "0"+ -DECIMAL_INTEGER: NON_ZERO_DIGIT DIGIT* | '0'+; - -/// octinteger ::= "0" ("o" | "O") octdigit+ -OCT_INTEGER: '0' [oO] OCT_DIGIT+; - -/// hexinteger ::= "0" ("x" | "X") hexdigit+ -HEX_INTEGER: '0' [xX] HEX_DIGIT+; - -/// bininteger ::= "0" ("b" | "B") bindigit+ -BIN_INTEGER: '0' [bB] BIN_DIGIT+; - -/// floatnumber ::= pointfloat | exponentfloat -FLOAT_NUMBER: POINT_FLOAT | EXPONENT_FLOAT; - -/// imagnumber ::= (floatnumber | intpart) ("j" | "J") -IMAG_NUMBER: ( FLOAT_NUMBER | INT_PART) [jJ]; - -DOT : '.'; -ELLIPSIS : '...'; -STAR : '*'; -OPEN_PAREN : '(' {this.openBrace();}; -CLOSE_PAREN : ')' {this.closeBrace();}; -COMMA : ','; -COLON : ':'; -SEMI_COLON : ';'; -POWER : '**'; -ASSIGN : '='; -OPEN_BRACK : '[' {this.openBrace();}; -CLOSE_BRACK : ']' {this.closeBrace();}; -OR_OP : '|'; -XOR : '^'; -AND_OP : '&'; -LEFT_SHIFT : '<<'; -RIGHT_SHIFT : '>>'; -ADD : '+'; -MINUS : '-'; -DIV : '/'; -MOD : '%'; -IDIV : '//'; -NOT_OP : '~'; -OPEN_BRACE : '{' {this.openBrace();}; -CLOSE_BRACE : '}' {this.closeBrace();}; -LESS_THAN : '<'; -GREATER_THAN : '>'; -EQUALS : '=='; -GT_EQ : '>='; -LT_EQ : '<='; -NOT_EQ_1 : '<>'; -NOT_EQ_2 : '!='; -AT : '@'; -ARROW : '->'; -ADD_ASSIGN : '+='; -SUB_ASSIGN : '-='; -MULT_ASSIGN : '*='; -AT_ASSIGN : '@='; -DIV_ASSIGN : '/='; -MOD_ASSIGN : '%='; -AND_ASSIGN : '&='; -OR_ASSIGN : '|='; -XOR_ASSIGN : '^='; -LEFT_SHIFT_ASSIGN : '<<='; -RIGHT_SHIFT_ASSIGN : '>>='; -POWER_ASSIGN : '**='; -IDIV_ASSIGN : '//='; - -SKIP_: ( SPACES | COMMENT | LINE_JOINING) -> skip; - -UNKNOWN_CHAR: .; - -/* - * fragments - */ - -/// shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"' -/// shortstringitem ::= shortstringchar | stringescapeseq -/// shortstringchar ::= -fragment SHORT_STRING: - '\'' (STRING_ESCAPE_SEQ | ~[\\\r\n\f'])* '\'' - | '"' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f"])* '"' -; -/// longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""' -fragment LONG_STRING: '\'\'\'' LONG_STRING_ITEM*? '\'\'\'' | '"""' LONG_STRING_ITEM*? '"""'; - -/// longstringitem ::= longstringchar | stringescapeseq -fragment LONG_STRING_ITEM: LONG_STRING_CHAR | STRING_ESCAPE_SEQ; - -/// longstringchar ::= -fragment LONG_STRING_CHAR: ~'\\'; - -/// stringescapeseq ::= "\" -fragment STRING_ESCAPE_SEQ: '\\' . | '\\' NEWLINE; - -/// nonzerodigit ::= "1"..."9" -fragment NON_ZERO_DIGIT: [1-9]; - -/// digit ::= "0"..."9" -fragment DIGIT: [0-9]; - -/// octdigit ::= "0"..."7" -fragment OCT_DIGIT: [0-7]; - -/// hexdigit ::= digit | "a"..."f" | "A"..."F" -fragment HEX_DIGIT: [0-9a-fA-F]; - -/// bindigit ::= "0" | "1" -fragment BIN_DIGIT: [01]; - -/// pointfloat ::= [intpart] fraction | intpart "." -fragment POINT_FLOAT: INT_PART? FRACTION | INT_PART '.'; - -/// exponentfloat ::= (intpart | pointfloat) exponent -fragment EXPONENT_FLOAT: ( INT_PART | POINT_FLOAT) EXPONENT; - -/// intpart ::= digit+ -fragment INT_PART: DIGIT+; - -/// fraction ::= "." digit+ -fragment FRACTION: '.' DIGIT+; - -/// exponent ::= ("e" | "E") ["+" | "-"] digit+ -fragment EXPONENT: [eE] [+-]? DIGIT+; - -/// shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"' -/// shortbytesitem ::= shortbyteschar | bytesescapeseq -fragment SHORT_BYTES: - '\'' (SHORT_BYTES_CHAR_NO_SINGLE_QUOTE | BYTES_ESCAPE_SEQ)* '\'' - | '"' ( SHORT_BYTES_CHAR_NO_DOUBLE_QUOTE | BYTES_ESCAPE_SEQ)* '"' -; - -/// longbytes ::= "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""' -fragment LONG_BYTES: '\'\'\'' LONG_BYTES_ITEM*? '\'\'\'' | '"""' LONG_BYTES_ITEM*? '"""'; - -/// longbytesitem ::= longbyteschar | bytesescapeseq -fragment LONG_BYTES_ITEM: LONG_BYTES_CHAR | BYTES_ESCAPE_SEQ; - -/// shortbyteschar ::= -fragment SHORT_BYTES_CHAR_NO_SINGLE_QUOTE: - [\u0000-\u0009] - | [\u000B-\u000C] - | [\u000E-\u0026] - | [\u0028-\u005B] - | [\u005D-\u007F] -; - -fragment SHORT_BYTES_CHAR_NO_DOUBLE_QUOTE: - [\u0000-\u0009] - | [\u000B-\u000C] - | [\u000E-\u0021] - | [\u0023-\u005B] - | [\u005D-\u007F] -; - -/// longbyteschar ::= -fragment LONG_BYTES_CHAR: [\u0000-\u005B] | [\u005D-\u007F]; - -/// bytesescapeseq ::= "\" -fragment BYTES_ESCAPE_SEQ: '\\' [\u0000-\u007F]; - -fragment SPACES: [ \t]+; - -fragment COMMENT: '#' ~[\r\n\f]*; - -fragment LINE_JOINING: '\\' SPACES? ( '\r'? '\n' | '\r' | '\f'); - -// TODO: ANTLR seems lack of some Unicode property support... -//$ curl https://www.unicode.org/Public/13.0.0/ucd/PropList.txt | grep Other_ID_ -//1885..1886 ; Other_ID_Start # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA -//2118 ; Other_ID_Start # Sm SCRIPT CAPITAL P -//212E ; Other_ID_Start # So ESTIMATED SYMBOL -//309B..309C ; Other_ID_Start # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK -//00B7 ; Other_ID_Continue # Po MIDDLE DOT -//0387 ; Other_ID_Continue # Po GREEK ANO TELEIA -//1369..1371 ; Other_ID_Continue # No [9] ETHIOPIC DIGIT ONE..ETHIOPIC DIGIT NINE -//19DA ; Other_ID_Continue # No NEW TAI LUE THAM DIGIT ONE - -fragment UNICODE_OIDS: '\u1885' ..'\u1886' | '\u2118' | '\u212e' | '\u309b' ..'\u309c'; - -fragment UNICODE_OIDC: '\u00b7' | '\u0387' | '\u1369' ..'\u1371' | '\u19da'; - -/// id_start ::= -fragment ID_START: - '_' - | [\p{L}] - | [\p{Nl}] - //| [\p{Other_ID_Start}] - | UNICODE_OIDS -; - -/// id_continue ::= -fragment ID_CONTINUE: - ID_START - | [\p{Mn}] - | [\p{Mc}] - | [\p{Nd}] - | [\p{Pc}] - //| [\p{Other_ID_Continue}] - | UNICODE_OIDC -; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Parser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Parser.g4 deleted file mode 100644 index 4c5a27cf..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/python/Python3Parser.g4 +++ /dev/null @@ -1,694 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Project : python3-parser; an ANTLR4 grammar for Python 3 - * https://github.com/bkiers/python3-parser - * Developed by : Bart Kiers, bart@big-o.nl - */ - -// Scraping from https://docs.python.org/3/reference/grammar.html - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar Python3Parser; - -options { - superClass = Python3ParserBase; - tokenVocab = Python3Lexer; -} - -// Insert here @header for C++ parser. - -// All comments that start with "///" are copy-pasted from -// The Python Language Reference - -single_input - : NEWLINE - | simple_stmts - | compound_stmt NEWLINE - ; - -file_input - : (NEWLINE | stmt)* EOF - ; - -eval_input - : testlist NEWLINE* EOF - ; - -decorator - : '@' dotted_name ('(' arglist? ')')? NEWLINE - ; - -decorators - : decorator+ - ; - -decorated - : decorators (classdef | funcdef | async_funcdef) - ; - -async_funcdef - : ASYNC funcdef - ; - -funcdef - : 'def' name parameters ('->' test)? ':' block - ; - -parameters - : '(' typedargslist? ')' - ; - -typedargslist - : ( - tfpdef ('=' test)? (',' tfpdef ('=' test)?)* ( - ',' ( - '*' tfpdef? (',' tfpdef ('=' test)?)* (',' ('**' tfpdef ','?)?)? - | '**' tfpdef ','? - )? - )? - | '*' tfpdef? (',' tfpdef ('=' test)?)* (',' ('**' tfpdef ','?)?)? - | '**' tfpdef ','? - ) - ; - -tfpdef - : name (':' test)? - ; - -varargslist - : ( - vfpdef ('=' test)? (',' vfpdef ('=' test)?)* ( - ',' ( - '*' vfpdef? (',' vfpdef ('=' test)?)* (',' ('**' vfpdef ','?)?)? - | '**' vfpdef (',')? - )? - )? - | '*' vfpdef? (',' vfpdef ('=' test)?)* (',' ('**' vfpdef ','?)?)? - | '**' vfpdef ','? - ) - ; - -vfpdef - : name - ; - -stmt - : simple_stmts - | compound_stmt - ; - -simple_stmts - : simple_stmt (';' simple_stmt)* ';'? NEWLINE - ; - -simple_stmt - : ( - expr_stmt - | del_stmt - | pass_stmt - | flow_stmt - | import_stmt - | global_stmt - | nonlocal_stmt - | assert_stmt - ) - ; - -expr_stmt - : testlist_star_expr ( - annassign - | augassign (yield_expr | testlist) - | ('=' (yield_expr | testlist_star_expr))* - ) - ; - -annassign - : ':' test ('=' test)? - ; - -testlist_star_expr - : (test | star_expr) (',' (test | star_expr))* ','? - ; - -augassign - : ( - '+=' - | '-=' - | '*=' - | '@=' - | '/=' - | '%=' - | '&=' - | '|=' - | '^=' - | '<<=' - | '>>=' - | '**=' - | '//=' - ) - ; - -// For normal and annotated assignments, additional restrictions enforced by the interpreter -del_stmt - : 'del' exprlist - ; - -pass_stmt - : 'pass' - ; - -flow_stmt - : break_stmt - | continue_stmt - | return_stmt - | raise_stmt - | yield_stmt - ; - -break_stmt - : 'break' - ; - -continue_stmt - : 'continue' - ; - -return_stmt - : 'return' testlist? - ; - -yield_stmt - : yield_expr - ; - -raise_stmt - : 'raise' (test ('from' test)?)? - ; - -import_stmt - : import_name - | import_from - ; - -import_name - : 'import' dotted_as_names - ; - -// note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS -import_from - : ( - 'from' (('.' | '...')* dotted_name | ('.' | '...')+) 'import' ( - '*' - | '(' import_as_names ')' - | import_as_names - ) - ) - ; - -import_as_name - : name ('as' name)? - ; - -dotted_as_name - : dotted_name ('as' name)? - ; - -import_as_names - : import_as_name (',' import_as_name)* ','? - ; - -dotted_as_names - : dotted_as_name (',' dotted_as_name)* - ; - -dotted_name - : name ('.' name)* - ; - -global_stmt - : 'global' name (',' name)* - ; - -nonlocal_stmt - : 'nonlocal' name (',' name)* - ; - -assert_stmt - : 'assert' test (',' test)? - ; - -compound_stmt - : if_stmt - | while_stmt - | for_stmt - | try_stmt - | with_stmt - | funcdef - | classdef - | decorated - | async_stmt - | match_stmt - ; - -async_stmt - : ASYNC (funcdef | with_stmt | for_stmt) - ; - -if_stmt - : 'if' test ':' block ('elif' test ':' block)* ('else' ':' block)? - ; - -while_stmt - : 'while' test ':' block ('else' ':' block)? - ; - -for_stmt - : 'for' exprlist 'in' testlist ':' block ('else' ':' block)? - ; - -try_stmt - : ( - 'try' ':' block ( - (except_clause ':' block)+ ('else' ':' block)? ('finally' ':' block)? - | 'finally' ':' block - ) - ) - ; - -with_stmt - : 'with' with_item (',' with_item)* ':' block - ; - -with_item - : test ('as' expr)? - ; - -// NB compile.c makes sure that the default except clause is last -except_clause - : 'except' (test ('as' name)?)? - ; - -block - : simple_stmts - | NEWLINE INDENT stmt+ DEDENT - ; - -match_stmt - : 'match' subject_expr ':' NEWLINE INDENT case_block+ DEDENT - ; - -subject_expr - : star_named_expression ',' star_named_expressions? - | test - ; - -star_named_expressions - : ',' star_named_expression+ ','? - ; - -star_named_expression - : '*' expr - | test - ; - -case_block - : 'case' patterns guard? ':' block - ; - -guard - : 'if' test - ; - -patterns - : open_sequence_pattern - | pattern - ; - -pattern - : as_pattern - | or_pattern - ; - -as_pattern - : or_pattern 'as' pattern_capture_target - ; - -or_pattern - : closed_pattern ('|' closed_pattern)* - ; - -closed_pattern - : literal_pattern - | capture_pattern - | wildcard_pattern - | value_pattern - | group_pattern - | sequence_pattern - | mapping_pattern - | class_pattern - ; - -literal_pattern - : signed_number { this.CannotBePlusMinus() }? - | complex_number - | strings - | 'None' - | 'True' - | 'False' - ; - -literal_expr - : signed_number { this.CannotBePlusMinus() }? - | complex_number - | strings - | 'None' - | 'True' - | 'False' - ; - -complex_number - : signed_real_number '+' imaginary_number - | signed_real_number '-' imaginary_number - ; - -signed_number - : NUMBER - | '-' NUMBER - ; - -signed_real_number - : real_number - | '-' real_number - ; - -real_number - : NUMBER - ; - -imaginary_number - : NUMBER - ; - -capture_pattern - : pattern_capture_target - ; - -pattern_capture_target - : /* cannot be '_' */ name { this.CannotBeDotLpEq() }? - ; - -wildcard_pattern - : '_' - ; - -value_pattern - : attr { this.CannotBeDotLpEq() }? - ; - -attr - : name ('.' name)+ - ; - -name_or_attr - : attr - | name - ; - -group_pattern - : '(' pattern ')' - ; - -sequence_pattern - : '[' maybe_sequence_pattern? ']' - | '(' open_sequence_pattern? ')' - ; - -open_sequence_pattern - : maybe_star_pattern ',' maybe_sequence_pattern? - ; - -maybe_sequence_pattern - : maybe_star_pattern (',' maybe_star_pattern)* ','? - ; - -maybe_star_pattern - : star_pattern - | pattern - ; - -star_pattern - : '*' pattern_capture_target - | '*' wildcard_pattern - ; - -mapping_pattern - : '{' '}' - | '{' double_star_pattern ','? '}' - | '{' items_pattern ',' double_star_pattern ','? '}' - | '{' items_pattern ','? '}' - ; - -items_pattern - : key_value_pattern (',' key_value_pattern)* - ; - -key_value_pattern - : (literal_expr | attr) ':' pattern - ; - -double_star_pattern - : '**' pattern_capture_target - ; - -class_pattern - : name_or_attr '(' ')' - | name_or_attr '(' positional_patterns ','? ')' - | name_or_attr '(' keyword_patterns ','? ')' - | name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')' - ; - -positional_patterns - : pattern (',' pattern)* - ; - -keyword_patterns - : keyword_pattern (',' keyword_pattern)* - ; - -keyword_pattern - : name '=' pattern - ; - -test - : or_test ('if' or_test 'else' test)? - | lambdef - ; - -test_nocond - : or_test - | lambdef_nocond - ; - -lambdef - : 'lambda' varargslist? ':' test - ; - -lambdef_nocond - : 'lambda' varargslist? ':' test_nocond - ; - -or_test - : and_test ('or' and_test)* - ; - -and_test - : not_test ('and' not_test)* - ; - -not_test - : 'not' not_test - | comparison - ; - -comparison - : expr (comp_op expr)* - ; - -// <> isn't actually a valid comparison operator in Python. It's here for the -// sake of a __future__ import described in PEP 401 (which really works :-) -comp_op - : '<' - | '>' - | '==' - | '>=' - | '<=' - | '<>' - | '!=' - | 'in' - | 'not' 'in' - | 'is' - | 'is' 'not' - ; - -star_expr - : '*' expr - ; - -expr - : atom_expr - | expr '**' expr - | ('+' | '-' | '~')+ expr - | expr ('*' | '@' | '/' | '%' | '//') expr - | expr ('+' | '-') expr - | expr ('<<' | '>>') expr - | expr '&' expr - | expr '^' expr - | expr '|' expr - ; - -//expr: xor_expr ('|' xor_expr)*; -//xor_expr: and_expr ('^' and_expr)*; -//and_expr: shift_expr ('&' shift_expr)*; -//shift_expr: arith_expr (('<<'|'>>') arith_expr)*; -//arith_expr: term (('+'|'-') term)*; -//term: factor (('*'|'@'|'/'|'%'|'//') factor)*; -//factor: ('+'|'-'|'~') factor | power; -//power: atom_expr ('**' factor)?; -atom_expr - : AWAIT? atom trailer* - ; - -atom - : '(' (yield_expr | testlist_comp)? ')' - | '[' testlist_comp? ']' - | '{' dictorsetmaker? '}' - | name - | NUMBER - | STRING+ - | '...' - | 'None' - | 'True' - | 'False' - ; - -name - : NAME - | '_' - | 'match' - ; - -testlist_comp - : (test | star_expr) (comp_for | (',' (test | star_expr))* ','?) - ; - -trailer - : '(' arglist? ')' - | '[' subscriptlist ']' - | '.' name - ; - -subscriptlist - : subscript_ (',' subscript_)* ','? - ; - -subscript_ - : test - | test? ':' test? sliceop? - ; - -sliceop - : ':' test? - ; - -exprlist - : (expr | star_expr) (',' (expr | star_expr))* ','? - ; - -testlist - : test (',' test)* ','? - ; - -dictorsetmaker - : ( - ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* ','?)) - | ((test | star_expr) (comp_for | (',' (test | star_expr))* ','?)) - ) - ; - -classdef - : 'class' name ('(' arglist? ')')? ':' block - ; - -arglist - : argument (',' argument)* ','? - ; - -// The reason that keywords are test nodes instead of NAME is that using NAME -// results in an ambiguity. ast.c makes sure it's a NAME. -// "test '=' test" is really "keyword '=' test", but we have no such token. -// These need to be in a single rule to avoid grammar that is ambiguous -// to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, -// we explicitly match '*' here, too, to give it proper precedence. -// Illegal combinations and orderings are blocked in ast.c: -// multiple (test comp_for) arguments are blocked; keyword unpackings -// that precede iterable unpackings are blocked; etc. -argument - : (test comp_for? | test '=' test | '**' test | '*' test) - ; - -comp_iter - : comp_for - | comp_if - ; - -comp_for - : ASYNC? 'for' exprlist 'in' or_test comp_iter? - ; - -comp_if - : 'if' test_nocond comp_iter? - ; - -// not used in grammar, but may appear in "node" passed from Parser to Compiler -encoding_decl - : name - ; - -yield_expr - : 'yield' yield_arg? - ; - -yield_arg - : 'from' test - | testlist - ; - -strings - : STRING+ - ; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustLexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustLexer.g4 deleted file mode 100644 index c18405e4..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustLexer.g4 +++ /dev/null @@ -1,270 +0,0 @@ -/* -Copyright (c) 2010 The Rust Project Developers -Copyright (c) 2020-2022 Student Main - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar RustLexer; - -// Insert here @header for C++ lexer. - -options -{ - superClass = RustLexerBase; -} - -// https://doc.rust-lang.org/reference/keywords.html strict -KW_AS : 'as'; -KW_BREAK : 'break'; -KW_CONST : 'const'; -KW_CONTINUE : 'continue'; -KW_CRATE : 'crate'; -KW_ELSE : 'else'; -KW_ENUM : 'enum'; -KW_EXTERN : 'extern'; -KW_FALSE : 'false'; -KW_FN : 'fn'; -KW_FOR : 'for'; -KW_IF : 'if'; -KW_IMPL : 'impl'; -KW_IN : 'in'; -KW_LET : 'let'; -KW_LOOP : 'loop'; -KW_MATCH : 'match'; -KW_MOD : 'mod'; -KW_MOVE : 'move'; -KW_MUT : 'mut'; -KW_PUB : 'pub'; -KW_REF : 'ref'; -KW_RETURN : 'return'; -KW_SELFVALUE : 'self'; -KW_SELFTYPE : 'Self'; -KW_STATIC : 'static'; -KW_STRUCT : 'struct'; -KW_SUPER : 'super'; -KW_TRAIT : 'trait'; -KW_TRUE : 'true'; -KW_TYPE : 'type'; -KW_UNSAFE : 'unsafe'; -KW_USE : 'use'; -KW_WHERE : 'where'; -KW_WHILE : 'while'; - -// 2018+ -KW_ASYNC : 'async'; -KW_AWAIT : 'await'; -KW_DYN : 'dyn'; - -// reserved -KW_ABSTRACT : 'abstract'; -KW_BECOME : 'become'; -KW_BOX : 'box'; -KW_DO : 'do'; -KW_FINAL : 'final'; -KW_MACRO : 'macro'; -KW_OVERRIDE : 'override'; -KW_PRIV : 'priv'; -KW_TYPEOF : 'typeof'; -KW_UNSIZED : 'unsized'; -KW_VIRTUAL : 'virtual'; -KW_YIELD : 'yield'; - -// reserved 2018+ -KW_TRY: 'try'; - -// weak -KW_UNION : 'union'; -KW_STATICLIFETIME : '\'static'; - -KW_MACRORULES : 'macro_rules'; -KW_UNDERLINELIFETIME : '\'_'; -KW_DOLLARCRATE : '$crate'; - -// rule itself allow any identifier, but keyword has been matched before -NON_KEYWORD_IDENTIFIER: XID_Start XID_Continue* | '_' XID_Continue+; - -// [\p{L}\p{Nl}\p{Other_ID_Start}-\p{Pattern_Syntax}-\p{Pattern_White_Space}] -fragment XID_Start: [\p{L}\p{Nl}] | UNICODE_OIDS; - -// [\p{ID_Start}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\p{Other_ID_Continue}-\p{Pattern_Syntax}-\p{Pattern_White_Space}] -fragment XID_Continue: XID_Start | [\p{Mn}\p{Mc}\p{Nd}\p{Pc}] | UNICODE_OIDC; - -fragment UNICODE_OIDS: '\u1885' ..'\u1886' | '\u2118' | '\u212e' | '\u309b' ..'\u309c'; - -fragment UNICODE_OIDC: '\u00b7' | '\u0387' | '\u1369' ..'\u1371' | '\u19da'; - -RAW_IDENTIFIER: 'r#' NON_KEYWORD_IDENTIFIER; -// comments https://doc.rust-lang.org/reference/comments.html -LINE_COMMENT: ('//' (~[/!] | '//') ~[\r\n]* | '//') -> channel (HIDDEN); - -BLOCK_COMMENT: - ( - '/*' (~[*!] | '**' | BLOCK_COMMENT_OR_DOC) (BLOCK_COMMENT_OR_DOC | ~[*])*? '*/' - | '/**/' - | '/***/' - ) -> channel (HIDDEN) -; - -INNER_LINE_DOC: '//!' ~[\n\r]* -> channel (HIDDEN); // isolated cr - -INNER_BLOCK_DOC: '/*!' ( BLOCK_COMMENT_OR_DOC | ~[*])*? '*/' -> channel (HIDDEN); - -OUTER_LINE_DOC: '///' (~[/] ~[\n\r]*)? -> channel (HIDDEN); // isolated cr - -OUTER_BLOCK_DOC: - '/**' (~[*] | BLOCK_COMMENT_OR_DOC) (BLOCK_COMMENT_OR_DOC | ~[*])*? '*/' -> channel (HIDDEN) -; - -BLOCK_COMMENT_OR_DOC: ( BLOCK_COMMENT | INNER_BLOCK_DOC | OUTER_BLOCK_DOC) -> channel (HIDDEN); - -SHEBANG: {this.SOF()}? '\ufeff'? '#!' ~[\r\n]* -> channel(HIDDEN); - -// whitespace https://doc.rust-lang.org/reference/whitespace.html -WHITESPACE : [\p{Zs}] -> channel(HIDDEN); -NEWLINE : ('\r\n' | [\r\n]) -> channel(HIDDEN); - -// tokens char and string -CHAR_LITERAL: '\'' ( ~['\\\n\r\t] | QUOTE_ESCAPE | ASCII_ESCAPE | UNICODE_ESCAPE) '\''; - -STRING_LITERAL: '"' ( ~["] | QUOTE_ESCAPE | ASCII_ESCAPE | UNICODE_ESCAPE | ESC_NEWLINE)* '"'; - -RAW_STRING_LITERAL: 'r' RAW_STRING_CONTENT; - -fragment RAW_STRING_CONTENT: '#' RAW_STRING_CONTENT '#' | '"' .*? '"'; - -BYTE_LITERAL: 'b\'' (. | QUOTE_ESCAPE | BYTE_ESCAPE) '\''; - -BYTE_STRING_LITERAL: 'b"' (~["] | QUOTE_ESCAPE | BYTE_ESCAPE)* '"'; - -RAW_BYTE_STRING_LITERAL: 'br' RAW_STRING_CONTENT; - -fragment ASCII_ESCAPE: '\\x' OCT_DIGIT HEX_DIGIT | COMMON_ESCAPE; - -fragment BYTE_ESCAPE: '\\x' HEX_DIGIT HEX_DIGIT | COMMON_ESCAPE; - -fragment COMMON_ESCAPE: '\\' [nrt\\0]; - -fragment UNICODE_ESCAPE: - '\\u{' HEX_DIGIT HEX_DIGIT? HEX_DIGIT? HEX_DIGIT? HEX_DIGIT? HEX_DIGIT? '}' -; - -fragment QUOTE_ESCAPE: '\\' ['"]; - -fragment ESC_NEWLINE: '\\' '\n'; - -// number - -INTEGER_LITERAL: ( DEC_LITERAL | BIN_LITERAL | OCT_LITERAL | HEX_LITERAL) INTEGER_SUFFIX?; - -DEC_LITERAL: DEC_DIGIT (DEC_DIGIT | '_')*; - -HEX_LITERAL: '0x' '_'* HEX_DIGIT (HEX_DIGIT | '_')*; - -OCT_LITERAL: '0o' '_'* OCT_DIGIT (OCT_DIGIT | '_')*; - -BIN_LITERAL: '0b' '_'* [01] [01_]*; - -FLOAT_LITERAL: - {this.FloatLiteralPossible()}? - ( - DEC_LITERAL '.' {this.FloatDotPossible()}? - | DEC_LITERAL ( '.' DEC_LITERAL)? FLOAT_EXPONENT? FLOAT_SUFFIX? - ) -; - -fragment INTEGER_SUFFIX: - 'u8' - | 'u16' - | 'u32' - | 'u64' - | 'u128' - | 'usize' - | 'i8' - | 'i16' - | 'i32' - | 'i64' - | 'i128' - | 'isize' -; - -fragment FLOAT_SUFFIX: 'f32' | 'f64'; - -fragment FLOAT_EXPONENT: [eE] [+-]? '_'* DEC_LITERAL; - -fragment OCT_DIGIT: [0-7]; - -fragment DEC_DIGIT: [0-9]; - -fragment HEX_DIGIT: [0-9a-fA-F]; - -// LIFETIME_TOKEN: '\'' IDENTIFIER_OR_KEYWORD | '\'_'; - -LIFETIME_OR_LABEL: '\'' NON_KEYWORD_IDENTIFIER; - -PLUS : '+'; -MINUS : '-'; -STAR : '*'; -SLASH : '/'; -PERCENT : '%'; -CARET : '^'; -NOT : '!'; -AND : '&'; -OR : '|'; -ANDAND : '&&'; -OROR : '||'; -//SHL: '<<'; SHR: '>>'; removed to avoid confusion in type parameter -PLUSEQ : '+='; -MINUSEQ : '-='; -STAREQ : '*='; -SLASHEQ : '/='; -PERCENTEQ : '%='; -CARETEQ : '^='; -ANDEQ : '&='; -OREQ : '|='; -SHLEQ : '<<='; -SHREQ : '>>='; -EQ : '='; -EQEQ : '=='; -NE : '!='; -GT : '>'; -LT : '<'; -GE : '>='; -LE : '<='; -AT : '@'; -UNDERSCORE : '_'; -DOT : '.'; -DOTDOT : '..'; -DOTDOTDOT : '...'; -DOTDOTEQ : '..='; -COMMA : ','; -SEMI : ';'; -COLON : ':'; -PATHSEP : '::'; -RARROW : '->'; -FATARROW : '=>'; -POUND : '#'; -DOLLAR : '$'; -QUESTION : '?'; - -LCURLYBRACE : '{'; -RCURLYBRACE : '}'; -LSQUAREBRACKET : '['; -RSQUAREBRACKET : ']'; -LPAREN : '('; -RPAREN : ')'; diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustParser.g4 deleted file mode 100644 index eaedf3bc..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/rust/RustParser.g4 +++ /dev/null @@ -1,1198 +0,0 @@ -/* -Copyright (c) 2010 The Rust Project Developers -Copyright (c) 2020-2022 Student Main - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar RustParser; - -// Insert here @header for C++ parser. - -options -{ - tokenVocab = RustLexer; - superClass = RustParserBase; -} - -// entry point -// 4 -crate - : innerAttribute* item* EOF - ; - -// 3 -macroInvocation - : simplePath NOT delimTokenTree - ; - -delimTokenTree - : LPAREN tokenTree* RPAREN - | LSQUAREBRACKET tokenTree* RSQUAREBRACKET - | LCURLYBRACE tokenTree* RCURLYBRACE - ; - -tokenTree - : tokenTreeToken+ - | delimTokenTree - ; - -tokenTreeToken - : macroIdentifierLikeToken - | macroLiteralToken - | macroPunctuationToken - | macroRepOp - | DOLLAR - ; - -macroInvocationSemi - : simplePath NOT LPAREN tokenTree* RPAREN SEMI - | simplePath NOT LSQUAREBRACKET tokenTree* RSQUAREBRACKET SEMI - | simplePath NOT LCURLYBRACE tokenTree* RCURLYBRACE - ; - -// 3.1 -macroRulesDefinition - : KW_MACRORULES NOT identifier macroRulesDef - ; - -macroRulesDef - : LPAREN macroRules RPAREN SEMI - | LSQUAREBRACKET macroRules RSQUAREBRACKET SEMI - | LCURLYBRACE macroRules RCURLYBRACE - ; - -macroRules - : macroRule (SEMI macroRule)* SEMI? - ; - -macroRule - : macroMatcher FATARROW macroTranscriber - ; - -macroMatcher - : LPAREN macroMatch* RPAREN - | LSQUAREBRACKET macroMatch* RSQUAREBRACKET - | LCURLYBRACE macroMatch* RCURLYBRACE - ; - -macroMatch - : macroMatchToken+ - | macroMatcher - | DOLLAR (identifier | KW_SELFVALUE) COLON macroFragSpec - | DOLLAR LPAREN macroMatch+ RPAREN macroRepSep? macroRepOp - ; - -macroMatchToken - : macroIdentifierLikeToken - | macroLiteralToken - | macroPunctuationToken - | macroRepOp - ; - -macroFragSpec - : identifier // do validate here is wasting token - ; - -macroRepSep - : macroIdentifierLikeToken - | macroLiteralToken - | macroPunctuationToken - | DOLLAR - ; - -macroRepOp - : STAR - | PLUS - | QUESTION - ; - -macroTranscriber - : delimTokenTree - ; - -//configurationPredicate -// : configurationOption | configurationAll | configurationAny | configurationNot ; configurationOption: identifier ( -// EQ (STRING_LITERAL | RAW_STRING_LITERAL))?; configurationAll: 'all' LPAREN configurationPredicateList? RPAREN; -// configurationAny: 'any' LPAREN configurationPredicateList? RPAREN; configurationNot: 'not' LPAREN configurationPredicate RPAREN; - -//configurationPredicateList -// : configurationPredicate (COMMA configurationPredicate)* COMMA? ; cfgAttribute: 'cfg' LPAREN configurationPredicate RPAREN; -// cfgAttrAttribute: 'cfg_attr' LPAREN configurationPredicate COMMA cfgAttrs? RPAREN; cfgAttrs: attr (COMMA attr)* COMMA?; - -// 6 -item - : outerAttribute* (visItem | macroItem) - ; - -visItem - : visibility? ( - module - | externCrate - | useDeclaration - | function_ - | typeAlias - | struct_ - | enumeration - | union_ - | constantItem - | staticItem - | trait_ - | implementation - | externBlock - ) - ; - -macroItem - : macroInvocationSemi - | macroRulesDefinition - ; - -// 6.1 -module - : KW_UNSAFE? KW_MOD identifier (SEMI | LCURLYBRACE innerAttribute* item* RCURLYBRACE) - ; - -// 6.2 -externCrate - : KW_EXTERN KW_CRATE crateRef asClause? SEMI - ; - -crateRef - : identifier - | KW_SELFVALUE - ; - -asClause - : KW_AS (identifier | UNDERSCORE) - ; - -// 6.3 -useDeclaration - : KW_USE useTree SEMI - ; - -useTree - : (simplePath? PATHSEP)? (STAR | LCURLYBRACE ( useTree (COMMA useTree)* COMMA?)? RCURLYBRACE) - | simplePath (KW_AS (identifier | UNDERSCORE))? - ; - -// 6.4 -function_ - : functionQualifiers KW_FN identifier genericParams? LPAREN functionParameters? RPAREN functionReturnType? whereClause? ( - blockExpression - | SEMI - ) - ; - -functionQualifiers - : KW_CONST? KW_ASYNC? KW_UNSAFE? (KW_EXTERN abi?)? - ; - -abi - : STRING_LITERAL - | RAW_STRING_LITERAL - ; - -functionParameters - : selfParam COMMA? - | (selfParam COMMA)? functionParam (COMMA functionParam)* COMMA? - ; - -selfParam - : outerAttribute* (shorthandSelf | typedSelf) - ; - -shorthandSelf - : (AND lifetime?)? KW_MUT? KW_SELFVALUE - ; - -typedSelf - : KW_MUT? KW_SELFVALUE COLON type_ - ; - -functionParam - : outerAttribute* (functionParamPattern | DOTDOTDOT | type_) - ; - -functionParamPattern - : pattern COLON (type_ | DOTDOTDOT) - ; - -functionReturnType - : RARROW type_ - ; - -// 6.5 -typeAlias - : KW_TYPE identifier genericParams? whereClause? (EQ type_)? SEMI - ; - -// 6.6 -struct_ - : structStruct - | tupleStruct - ; - -structStruct - : KW_STRUCT identifier genericParams? whereClause? (LCURLYBRACE structFields? RCURLYBRACE | SEMI) - ; - -tupleStruct - : KW_STRUCT identifier genericParams? LPAREN tupleFields? RPAREN whereClause? SEMI - ; - -structFields - : structField (COMMA structField)* COMMA? - ; - -structField - : outerAttribute* visibility? identifier COLON type_ - ; - -tupleFields - : tupleField (COMMA tupleField)* COMMA? - ; - -tupleField - : outerAttribute* visibility? type_ - ; - -// 6.7 -enumeration - : KW_ENUM identifier genericParams? whereClause? LCURLYBRACE enumItems? RCURLYBRACE - ; - -enumItems - : enumItem (COMMA enumItem)* COMMA? - ; - -enumItem - : outerAttribute* visibility? identifier ( - enumItemTuple - | enumItemStruct - | enumItemDiscriminant - )? - ; - -enumItemTuple - : LPAREN tupleFields? RPAREN - ; - -enumItemStruct - : LCURLYBRACE structFields? RCURLYBRACE - ; - -enumItemDiscriminant - : EQ expression - ; - -// 6.8 -union_ - : KW_UNION identifier genericParams? whereClause? LCURLYBRACE structFields RCURLYBRACE - ; - -// 6.9 -constantItem - : KW_CONST (identifier | UNDERSCORE) COLON type_ (EQ expression)? SEMI - ; - -// 6.10 -staticItem - : KW_STATIC KW_MUT? identifier COLON type_ (EQ expression)? SEMI - ; - -// 6.11 -trait_ - : KW_UNSAFE? KW_TRAIT identifier genericParams? (COLON typeParamBounds?)? whereClause? LCURLYBRACE innerAttribute* associatedItem* RCURLYBRACE - ; - -// 6.12 -implementation - : inherentImpl - | traitImpl - ; - -inherentImpl - : KW_IMPL genericParams? type_ whereClause? LCURLYBRACE innerAttribute* associatedItem* RCURLYBRACE - ; - -traitImpl - : KW_UNSAFE? KW_IMPL genericParams? NOT? typePath KW_FOR type_ whereClause? LCURLYBRACE innerAttribute* associatedItem* RCURLYBRACE - ; - -// 6.13 -externBlock - : KW_UNSAFE? KW_EXTERN abi? LCURLYBRACE innerAttribute* externalItem* RCURLYBRACE - ; - -externalItem - : outerAttribute* (macroInvocationSemi | visibility? ( staticItem | function_)) - ; - -// 6.14 -genericParams - : LT ((genericParam COMMA)* genericParam COMMA?)? GT - ; - -genericParam - : outerAttribute* (lifetimeParam | typeParam | constParam) - ; - -lifetimeParam - : outerAttribute? LIFETIME_OR_LABEL (COLON lifetimeBounds)? - ; - -typeParam - : outerAttribute? identifier (COLON typeParamBounds?)? (EQ type_)? - ; - -constParam - : KW_CONST identifier COLON type_ - ; - -whereClause - : KW_WHERE (whereClauseItem COMMA)* whereClauseItem? - ; - -whereClauseItem - : lifetimeWhereClauseItem - | typeBoundWhereClauseItem - ; - -lifetimeWhereClauseItem - : lifetime COLON lifetimeBounds - ; - -typeBoundWhereClauseItem - : forLifetimes? type_ COLON typeParamBounds? - ; - -forLifetimes - : KW_FOR genericParams - ; - -// 6.15 -associatedItem - : outerAttribute* (macroInvocationSemi | visibility? ( typeAlias | constantItem | function_)) - ; - -// 7 -innerAttribute - : POUND NOT LSQUAREBRACKET attr RSQUAREBRACKET - ; - -outerAttribute - : POUND LSQUAREBRACKET attr RSQUAREBRACKET - ; - -attr - : simplePath attrInput? - ; - -attrInput - : delimTokenTree - | EQ literalExpression - ; // w/o suffix - -//metaItem -// : simplePath ( EQ literalExpression //w | LPAREN metaSeq RPAREN )? ; metaSeq: metaItemInner (COMMA metaItemInner)* COMMA?; -// metaItemInner: metaItem | literalExpression; // w - -//metaWord: identifier; metaNameValueStr: identifier EQ ( STRING_LITERAL | RAW_STRING_LITERAL); metaListPaths: -// identifier LPAREN ( simplePath (COMMA simplePath)* COMMA?)? RPAREN; metaListIdents: identifier LPAREN ( identifier (COMMA -// identifier)* COMMA?)? RPAREN; metaListNameValueStr : identifier LPAREN (metaNameValueStr ( COMMA metaNameValueStr)* COMMA?)? RPAREN -// ; - -// 8 -statement - : SEMI - | item - | letStatement - | expressionStatement - | macroInvocationSemi - ; - -letStatement - : outerAttribute* KW_LET patternNoTopAlt (COLON type_)? (EQ expression)? SEMI - ; - -expressionStatement - : expression SEMI - | expressionWithBlock SEMI? - ; - -// 8.2 -expression - : outerAttribute+ expression # AttributedExpression // technical, remove left recursive - | literalExpression # LiteralExpression_ - | pathExpression # PathExpression_ - | expression DOT pathExprSegment LPAREN callParams? RPAREN # MethodCallExpression // 8.2.10 - | expression DOT identifier # FieldExpression // 8.2.11 - | expression DOT tupleIndex # TupleIndexingExpression // 8.2.7 - | expression DOT KW_AWAIT # AwaitExpression // 8.2.18 - | expression LPAREN callParams? RPAREN # CallExpression // 8.2.9 - | expression LSQUAREBRACKET expression RSQUAREBRACKET # IndexExpression // 8.2.6 - | expression QUESTION # ErrorPropagationExpression // 8.2.4 - | (AND | ANDAND) KW_MUT? expression # BorrowExpression // 8.2.4 - | STAR expression # DereferenceExpression // 8.2.4 - | (MINUS | NOT) expression # NegationExpression // 8.2.4 - | expression KW_AS typeNoBounds # TypeCastExpression // 8.2.4 - | expression (STAR | SLASH | PERCENT) expression # ArithmeticOrLogicalExpression // 8.2.4 - | expression (PLUS | MINUS) expression # ArithmeticOrLogicalExpression // 8.2.4 - | expression (shl | shr) expression # ArithmeticOrLogicalExpression // 8.2.4 - | expression AND expression # ArithmeticOrLogicalExpression // 8.2.4 - | expression CARET expression # ArithmeticOrLogicalExpression // 8.2.4 - | expression OR expression # ArithmeticOrLogicalExpression // 8.2.4 - | expression comparisonOperator expression # ComparisonExpression // 8.2.4 - | expression ANDAND expression # LazyBooleanExpression // 8.2.4 - | expression OROR expression # LazyBooleanExpression // 8.2.4 - | expression DOTDOT expression? # RangeExpression // 8.2.14 - | DOTDOT expression? # RangeExpression // 8.2.14 - | DOTDOTEQ expression # RangeExpression // 8.2.14 - | expression DOTDOTEQ expression # RangeExpression // 8.2.14 - | expression EQ expression # AssignmentExpression // 8.2.4 - | expression compoundAssignOperator expression # CompoundAssignmentExpression // 8.2.4 - | KW_CONTINUE LIFETIME_OR_LABEL? expression? # ContinueExpression // 8.2.13 - | KW_BREAK LIFETIME_OR_LABEL? expression? # BreakExpression // 8.2.13 - | KW_RETURN expression? # ReturnExpression // 8.2.17 - | LPAREN innerAttribute* expression RPAREN # GroupedExpression // 8.2.5 - | LSQUAREBRACKET innerAttribute* arrayElements? RSQUAREBRACKET # ArrayExpression // 8.2.6 - | LPAREN innerAttribute* tupleElements? RPAREN # TupleExpression // 8.2.7 - | structExpression # StructExpression_ // 8.2.8 - | enumerationVariantExpression # EnumerationVariantExpression_ - | closureExpression # ClosureExpression_ // 8.2.12 - | expressionWithBlock # ExpressionWithBlock_ - | macroInvocation # MacroInvocationAsExpression - ; - -comparisonOperator - : EQEQ - | NE - | GT - | LT - | GE - | LE - ; - -compoundAssignOperator - : PLUSEQ - | MINUSEQ - | STAREQ - | SLASHEQ - | PERCENTEQ - | ANDEQ - | OREQ - | CARETEQ - | SHLEQ - | SHREQ - ; - -expressionWithBlock - : outerAttribute+ expressionWithBlock // technical - | blockExpression - | asyncBlockExpression - | unsafeBlockExpression - | loopExpression - | ifExpression - | ifLetExpression - | matchExpression - ; - -// 8.2.1 -literalExpression - : CHAR_LITERAL - | STRING_LITERAL - | RAW_STRING_LITERAL - | BYTE_LITERAL - | BYTE_STRING_LITERAL - | RAW_BYTE_STRING_LITERAL - | INTEGER_LITERAL - | FLOAT_LITERAL - | KW_TRUE - | KW_FALSE - ; - -// 8.2.2 -pathExpression - : pathInExpression - | qualifiedPathInExpression - ; - -// 8.2.3 -blockExpression - : LCURLYBRACE innerAttribute* statements? RCURLYBRACE - ; - -statements - : statement+ expression? - | expression - ; - -asyncBlockExpression - : KW_ASYNC KW_MOVE? blockExpression - ; - -unsafeBlockExpression - : KW_UNSAFE blockExpression - ; - -// 8.2.6 -arrayElements - : expression (COMMA expression)* COMMA? - | expression SEMI expression - ; - -// 8.2.7 -tupleElements - : (expression COMMA)+ expression? - ; - -tupleIndex - : INTEGER_LITERAL - ; - -// 8.2.8 -structExpression - : structExprStruct - | structExprTuple - | structExprUnit - ; - -structExprStruct - : pathInExpression LCURLYBRACE innerAttribute* (structExprFields | structBase)? RCURLYBRACE - ; - -structExprFields - : structExprField (COMMA structExprField)* (COMMA structBase | COMMA?) - ; - -// outerAttribute here is not in doc -structExprField - : outerAttribute* (identifier | (identifier | tupleIndex) COLON expression) - ; - -structBase - : DOTDOT expression - ; - -structExprTuple - : pathInExpression LPAREN innerAttribute* (expression ( COMMA expression)* COMMA?)? RPAREN - ; - -structExprUnit - : pathInExpression - ; - -enumerationVariantExpression - : enumExprStruct - | enumExprTuple - | enumExprFieldless - ; - -enumExprStruct - : pathInExpression LCURLYBRACE enumExprFields? RCURLYBRACE - ; - -enumExprFields - : enumExprField (COMMA enumExprField)* COMMA? - ; - -enumExprField - : identifier - | (identifier | tupleIndex) COLON expression - ; - -enumExprTuple - : pathInExpression LPAREN (expression (COMMA expression)* COMMA?)? RPAREN - ; - -enumExprFieldless - : pathInExpression - ; - -// 8.2.9 -callParams - : expression (COMMA expression)* COMMA? - ; - -// 8.2.12 -closureExpression - : KW_MOVE? (OROR | OR closureParameters? OR) (expression | RARROW typeNoBounds blockExpression) - ; - -closureParameters - : closureParam (COMMA closureParam)* COMMA? - ; - -closureParam - : outerAttribute* pattern (COLON type_)? - ; - -// 8.2.13 -loopExpression - : loopLabel? ( - infiniteLoopExpression - | predicateLoopExpression - | predicatePatternLoopExpression - | iteratorLoopExpression - ) - ; - -infiniteLoopExpression - : KW_LOOP blockExpression - ; - -predicateLoopExpression - : KW_WHILE expression /*except structExpression*/ blockExpression - ; - -predicatePatternLoopExpression - : KW_WHILE KW_LET pattern EQ expression blockExpression - ; - -iteratorLoopExpression - : KW_FOR pattern KW_IN expression blockExpression - ; - -loopLabel - : LIFETIME_OR_LABEL COLON - ; - -// 8.2.15 -ifExpression - : KW_IF expression blockExpression (KW_ELSE (blockExpression | ifExpression | ifLetExpression))? - ; - -ifLetExpression - : KW_IF KW_LET pattern EQ expression blockExpression ( - KW_ELSE (blockExpression | ifExpression | ifLetExpression) - )? - ; - -// 8.2.16 -matchExpression - : KW_MATCH expression LCURLYBRACE innerAttribute* matchArms? RCURLYBRACE - ; - -matchArms - : (matchArm FATARROW matchArmExpression)* matchArm FATARROW expression COMMA? - ; - -matchArmExpression - : expression COMMA - | expressionWithBlock COMMA? - ; - -matchArm - : outerAttribute* pattern matchArmGuard? - ; - -matchArmGuard - : KW_IF expression - ; - -// 9 -pattern - : OR? patternNoTopAlt (OR patternNoTopAlt)* - ; - -patternNoTopAlt - : patternWithoutRange - | rangePattern - ; - -patternWithoutRange - : literalPattern - | identifierPattern - | wildcardPattern - | restPattern - | referencePattern - | structPattern - | tupleStructPattern - | tuplePattern - | groupedPattern - | slicePattern - | pathPattern - | macroInvocation - ; - -literalPattern - : KW_TRUE - | KW_FALSE - | CHAR_LITERAL - | BYTE_LITERAL - | STRING_LITERAL - | RAW_STRING_LITERAL - | BYTE_STRING_LITERAL - | RAW_BYTE_STRING_LITERAL - | MINUS? INTEGER_LITERAL - | MINUS? FLOAT_LITERAL - ; - -identifierPattern - : KW_REF? KW_MUT? identifier (AT pattern)? - ; - -wildcardPattern - : UNDERSCORE - ; - -restPattern - : DOTDOT - ; - -rangePattern - : rangePatternBound DOTDOTEQ rangePatternBound # InclusiveRangePattern - | rangePatternBound DOTDOT # HalfOpenRangePattern - | rangePatternBound DOTDOTDOT rangePatternBound # ObsoleteRangePattern - ; - -rangePatternBound - : CHAR_LITERAL - | BYTE_LITERAL - | MINUS? INTEGER_LITERAL - | MINUS? FLOAT_LITERAL - | pathPattern - ; - -referencePattern - : (AND | ANDAND) KW_MUT? patternWithoutRange - ; - -structPattern - : pathInExpression LCURLYBRACE structPatternElements? RCURLYBRACE - ; - -structPatternElements - : structPatternFields (COMMA structPatternEtCetera?)? - | structPatternEtCetera - ; - -structPatternFields - : structPatternField (COMMA structPatternField)* - ; - -structPatternField - : outerAttribute* (tupleIndex COLON pattern | identifier COLON pattern | KW_REF? KW_MUT? identifier) - ; - -structPatternEtCetera - : outerAttribute* DOTDOT - ; - -tupleStructPattern - : pathInExpression LPAREN tupleStructItems? RPAREN - ; - -tupleStructItems - : pattern (COMMA pattern)* COMMA? - ; - -tuplePattern - : LPAREN tuplePatternItems? RPAREN - ; - -tuplePatternItems - : pattern COMMA - | restPattern - | pattern (COMMA pattern)+ COMMA? - ; - -groupedPattern - : LPAREN pattern RPAREN - ; - -slicePattern - : LSQUAREBRACKET slicePatternItems? RSQUAREBRACKET - ; - -slicePatternItems - : pattern (COMMA pattern)* COMMA? - ; - -pathPattern - : pathInExpression - | qualifiedPathInExpression - ; - -// 10.1 -type_ - : typeNoBounds - | implTraitType - | traitObjectType - ; - -typeNoBounds - : parenthesizedType - | implTraitTypeOneBound - | traitObjectTypeOneBound - | typePath - | tupleType - | neverType - | rawPointerType - | referenceType - | arrayType - | sliceType - | inferredType - | qualifiedPathInType - | bareFunctionType - | macroInvocation - ; - -parenthesizedType - : LPAREN type_ RPAREN - ; - -// 10.1.4 -neverType - : NOT - ; - -// 10.1.5 -tupleType - : LPAREN ((type_ COMMA)+ type_?)? RPAREN - ; - -// 10.1.6 -arrayType - : LSQUAREBRACKET type_ SEMI expression RSQUAREBRACKET - ; - -// 10.1.7 -sliceType - : LSQUAREBRACKET type_ RSQUAREBRACKET - ; - -// 10.1.13 -referenceType - : AND lifetime? KW_MUT? typeNoBounds - ; - -rawPointerType - : STAR (KW_MUT | KW_CONST) typeNoBounds - ; - -// 10.1.14 -bareFunctionType - : forLifetimes? functionTypeQualifiers KW_FN LPAREN functionParametersMaybeNamedVariadic? RPAREN bareFunctionReturnType? - ; - -functionTypeQualifiers - : KW_UNSAFE? (KW_EXTERN abi?)? - ; - -bareFunctionReturnType - : RARROW typeNoBounds - ; - -functionParametersMaybeNamedVariadic - : maybeNamedFunctionParameters - | maybeNamedFunctionParametersVariadic - ; - -maybeNamedFunctionParameters - : maybeNamedParam (COMMA maybeNamedParam)* COMMA? - ; - -maybeNamedParam - : outerAttribute* ((identifier | UNDERSCORE) COLON)? type_ - ; - -maybeNamedFunctionParametersVariadic - : (maybeNamedParam COMMA)* maybeNamedParam COMMA outerAttribute* DOTDOTDOT - ; - -// 10.1.15 -traitObjectType - : KW_DYN? typeParamBounds - ; - -traitObjectTypeOneBound - : KW_DYN? traitBound - ; - -implTraitType - : KW_IMPL typeParamBounds - ; - -implTraitTypeOneBound - : KW_IMPL traitBound - ; - -// 10.1.18 -inferredType - : UNDERSCORE - ; - -// 10.6 -typeParamBounds - : typeParamBound (PLUS typeParamBound)* PLUS? - ; - -typeParamBound - : lifetime - | traitBound - ; - -traitBound - : QUESTION? forLifetimes? typePath - | LPAREN QUESTION? forLifetimes? typePath RPAREN - ; - -lifetimeBounds - : (lifetime PLUS)* lifetime? - ; - -lifetime - : LIFETIME_OR_LABEL - | KW_STATICLIFETIME - | KW_UNDERLINELIFETIME - ; - -// 12.4 -simplePath - : PATHSEP? simplePathSegment (PATHSEP simplePathSegment)* - ; - -simplePathSegment - : identifier - | KW_SUPER - | KW_SELFVALUE - | KW_CRATE - | KW_DOLLARCRATE - ; - -pathInExpression - : PATHSEP? pathExprSegment (PATHSEP pathExprSegment)* - ; - -pathExprSegment - : pathIdentSegment (PATHSEP genericArgs)? - ; - -pathIdentSegment - : identifier - | KW_SUPER - | KW_SELFVALUE - | KW_SELFTYPE - | KW_CRATE - | KW_DOLLARCRATE - ; - -//TODO: let x : T<_>=something; -genericArgs - : LT GT - | LT genericArgsLifetimes (COMMA genericArgsTypes)? (COMMA genericArgsBindings)? COMMA? GT - | LT genericArgsTypes (COMMA genericArgsBindings)? COMMA? GT - | LT (genericArg COMMA)* genericArg COMMA? GT - ; - -genericArg - : lifetime - | type_ - | genericArgsConst - | genericArgsBinding - ; - -genericArgsConst - : blockExpression - | MINUS? literalExpression - | simplePathSegment - ; - -genericArgsLifetimes - : lifetime (COMMA lifetime)* - ; - -genericArgsTypes - : type_ (COMMA type_)* - ; - -genericArgsBindings - : genericArgsBinding (COMMA genericArgsBinding)* - ; - -genericArgsBinding - : identifier EQ type_ - ; - -qualifiedPathInExpression - : qualifiedPathType (PATHSEP pathExprSegment)+ - ; - -qualifiedPathType - : LT type_ (KW_AS typePath)? GT - ; - -qualifiedPathInType - : qualifiedPathType (PATHSEP typePathSegment)+ - ; - -typePath - : PATHSEP? typePathSegment (PATHSEP typePathSegment)* - ; - -typePathSegment - : pathIdentSegment PATHSEP? (genericArgs | typePathFn)? - ; - -typePathFn - : LPAREN typePathInputs? RPAREN (RARROW type_)? - ; - -typePathInputs - : type_ (COMMA type_)* COMMA? - ; - -// 12.6 -visibility - : KW_PUB (LPAREN ( KW_CRATE | KW_SELFVALUE | KW_SUPER | KW_IN simplePath) RPAREN)? - ; - -// technical -identifier - : NON_KEYWORD_IDENTIFIER - | RAW_IDENTIFIER - | KW_MACRORULES - ; - -keyword - : KW_AS - | KW_BREAK - | KW_CONST - | KW_CONTINUE - | KW_CRATE - | KW_ELSE - | KW_ENUM - | KW_EXTERN - | KW_FALSE - | KW_FN - | KW_FOR - | KW_IF - | KW_IMPL - | KW_IN - | KW_LET - | KW_LOOP - | KW_MATCH - | KW_MOD - | KW_MOVE - | KW_MUT - | KW_PUB - | KW_REF - | KW_RETURN - | KW_SELFVALUE - | KW_SELFTYPE - | KW_STATIC - | KW_STRUCT - | KW_SUPER - | KW_TRAIT - | KW_TRUE - | KW_TYPE - | KW_UNSAFE - | KW_USE - | KW_WHERE - | KW_WHILE - - // 2018+ - | KW_ASYNC - | KW_AWAIT - | KW_DYN - // reserved - | KW_ABSTRACT - | KW_BECOME - | KW_BOX - | KW_DO - | KW_FINAL - | KW_MACRO - | KW_OVERRIDE - | KW_PRIV - | KW_TYPEOF - | KW_UNSIZED - | KW_VIRTUAL - | KW_YIELD - | KW_TRY - | KW_UNION - | KW_STATICLIFETIME - ; - -macroIdentifierLikeToken - : keyword - | identifier - | KW_MACRORULES - | KW_UNDERLINELIFETIME - | KW_DOLLARCRATE - | LIFETIME_OR_LABEL - ; - -macroLiteralToken - : literalExpression - ; - -// macroDelimiterToken: LCURLYBRACE | RCURLYBRACE | LSQUAREBRACKET | RSQUAREBRACKET | LPAREN | RPAREN; -macroPunctuationToken - : MINUS - //| PLUS | STAR - | SLASH - | PERCENT - | CARET - | NOT - | AND - | OR - | ANDAND - | OROR - // already covered by LT and GT in macro | shl | shr - | PLUSEQ - | MINUSEQ - | STAREQ - | SLASHEQ - | PERCENTEQ - | CARETEQ - | ANDEQ - | OREQ - | SHLEQ - | SHREQ - | EQ - | EQEQ - | NE - | GT - | LT - | GE - | LE - | AT - | UNDERSCORE - | DOT - | DOTDOT - | DOTDOTDOT - | DOTDOTEQ - | COMMA - | SEMI - | COLON - | PATHSEP - | RARROW - | FATARROW - | POUND - //| DOLLAR | QUESTION - ; - -shl - : LT {this.NextLT()}? LT - ; - -shr - : GT {this.NextGT()}? GT - ; diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/scala/Scala.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/scala/Scala.g4 deleted file mode 100644 index 2bdc0e3c..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/scala/Scala.g4 +++ /dev/null @@ -1,1383 +0,0 @@ -/* - [The "BSD licence"] - Copyright (c) 2014 Leonardo Lucena - Copyright (c) 2018 Andrey Stolyarov - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/* - Derived from https://github.com/scala/scala/blob/2.12.x/spec/13-syntax-summary.md - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -grammar Scala; - -literal - : '-'? IntegerLiteral - | '-'? FloatingPointLiteral - | BooleanLiteral - | CharacterLiteral - | StringLiteral - | SymbolLiteral - | 'null' - ; - -qualId - : Id ('.' Id)* - ; - -ids - : Id (',' Id)* - ; - -stableId - : Id - | stableId '.' Id - | (Id '.')? ('this' | 'super' classQualifier? '.' Id) - ; - -classQualifier - : '[' Id ']' - ; - -type_ - : functionArgTypes '=>' type_ - | infixType existentialClause? - ; - -functionArgTypes - : infixType - | '(' (paramType (',' paramType)*)? ')' - ; - -existentialClause - : 'forSome' '{' existentialDcl+ '}' - ; - -existentialDcl - : 'type' typeDcl - | 'val' valDcl - ; - -infixType - : compoundType (Id compoundType)* - ; - -compoundType - : annotType ('with' annotType)* refinement? - | refinement - ; - -annotType - : simpleType annotation* - ; - -simpleType - : simpleType typeArgs - | simpleType '#' Id - | stableId ('.' 'type')? - | '(' types ')' - ; - -typeArgs - : '[' types ']' - ; - -types - : type_ (',' type_)* - ; - -refinement - : NL? '{' refineStat+ '}' - ; - -refineStat - : dcl - | 'type' typeDef - ; - -typePat - : type_ - ; - -ascription - : ':' infixType - | ':' annotation+ - | ':' '_' '*' - ; - -expr - : (bindings | 'implicit'? Id | '_') '=>' expr - | expr1 - ; - -expr1 - : 'if' '(' expr ')' NL* expr ('else' expr)? - | 'while' '(' expr ')' NL* expr - | 'try' expr ('catch' expr)? ('finally' expr)? - | 'do' expr 'while' '(' expr ')' - | 'for' ('(' enumerators ')' | '{' enumerators '}') 'yield'? expr - | 'throw' expr - | 'return' expr? - | ((simpleExpr | simpleExpr1 '_'?) '.')? Id '=' expr - | simpleExpr1 argumentExprs '=' expr - | postfixExpr ascription? - | postfixExpr 'match' '{' caseClauses '}' - ; - -prefixDef - : '-' - | '+' - | '~' - | '!' - ; - -postfixExpr - : infixExpr Id? (prefixDef simpleExpr1)* NL? - ; - -infixExpr - : prefixExpr - | infixExpr Id NL? infixExpr - ; - -prefixExpr - : prefixDef? (simpleExpr | simpleExpr1 '_'?) - ; - -simpleExpr - : 'new' (classTemplate | templateBody) - | blockExpr - ; - -// Dublicate lines to prevent left-recursive code. -// can't use (simpleExpr|simpleExpr1) '.' Id -simpleExpr1 - : literal - | stableId - | '_' - | '(' exprs? ')' - | simpleExpr '.' Id - | simpleExpr1 '_'? '.' Id - | simpleExpr typeArgs - | simpleExpr1 '_'? typeArgs - | simpleExpr1 argumentExprs - ; - -exprs - : expr (',' expr)* - ; - -argumentExprs - : '(' args ')' - | '{' args '}' - | NL? blockExpr - ; - -args - : exprs? - | (exprs ',')? postfixExpr (':' | '_' | '*')? - ; - -blockExpr - : '{' caseClauses '}' - | '{' block '}' - ; - -block - : blockStat+ resultExpr? - ; - -blockStat - : import_ - | annotation* ('implicit' | 'lazy')? def_ - | annotation* localModifier* tmplDef - | expr1 - ; - -resultExpr - : expr1 - | (bindings | ('implicit'? Id | '_') ':' compoundType) '=>' block - ; - -enumerators - : generator+ - ; - -generator - : pattern1 '<-' expr (guard_ | pattern1 '=' expr)* - ; - -caseClauses - : caseClause+ - ; - -caseClause - : 'case' pattern guard_? '=>' block - ; - -guard_ - : 'if' postfixExpr - ; - -pattern - : pattern1 ('|' pattern1)* - ; - -pattern1 - : (BoundVarid | '_' | Id) ':' typePat - | pattern2 - ; - -pattern2 - : Id ('@' pattern3)? - | pattern3 - ; - -pattern3 - : simplePattern - | simplePattern (Id NL? simplePattern)* - ; - -simplePattern - : '_' - | Varid - | literal - | stableId ('(' patterns? ')')? - | stableId '(' (patterns ',')? (Id '@')? '_' '*' ')' - | '(' patterns? ')' - ; - -patterns - : pattern (',' patterns)? - | '_' '*' - ; - -typeParamClause - : '[' variantTypeParam (',' variantTypeParam)* ']' - ; - -funTypeParamClause - : '[' typeParam (',' typeParam)* ']' - ; - -variantTypeParam - : annotation* ('+' | '-')? typeParam - ; - -typeParam - : (Id | '_') typeParamClause? ('>:' type_)? ('<:' type_)? ('<%' type_)* (':' type_)* - ; - -paramClauses - : paramClause* (NL? '(' 'implicit' params ')')? - ; - -paramClause - : NL? '(' params? ')' - ; - -params - : param (',' param)* - ; - -param - : annotation* Id (':' paramType)? ('=' expr)? - ; - -paramType - : type_ - | '=>' type_ - | type_ '*' - ; - -classParamClauses - : classParamClause* (NL? '(' 'implicit' classParams ')')? - ; - -classParamClause - : NL? '(' classParams? ')' - ; - -classParams - : classParam (',' classParam)* - ; - -classParam - : annotation* modifier* ('val' | 'var')? Id ':' paramType ('=' expr)? - ; - -bindings - : '(' binding (',' binding)* ')' - ; - -binding - : (Id | '_') (':' type_)? - ; - -modifier - : localModifier - | accessModifier - | 'override' - ; - -localModifier - : 'abstract' - | 'final' - | 'sealed' - | 'implicit' - | 'lazy' - ; - -accessModifier - : ('private' | 'protected') accessQualifier? - ; - -accessQualifier - : '[' (Id | 'this') ']' - ; - -annotation - : '@' simpleType argumentExprs* - ; - -constrAnnotation - : '@' simpleType argumentExprs - ; - -templateBody - : NL? '{' selfType? templateStat+ '}' - ; - -templateStat - : import_ - | (annotation NL?)* modifier* def_ - | (annotation NL?)* modifier* dcl - | expr - ; - -selfType - : Id (':' type_)? '=>' - | 'this' ':' type_ '=>' - ; - -import_ - : 'import' importExpr (',' importExpr)* - ; - -importExpr - : stableId ('.' (Id | '_' | importSelectors))? - ; - -importSelectors - : '{' (importSelector ',')* (importSelector | '_') '}' - ; - -importSelector - : Id ('=>' (Id | '_'))? - ; - -dcl - : 'val' valDcl - | 'var' varDcl - | 'def' funDcl - | 'type' NL* typeDcl - ; - -valDcl - : ids ':' type_ - ; - -varDcl - : ids ':' type_ - ; - -funDcl - : funSig (':' type_)? - ; - -funSig - : Id funTypeParamClause? paramClauses - ; - -typeDcl - : Id typeParamClause? ('>:' type_)? ('<:' type_)? - ; - -patVarDef - : 'val' patDef - | 'var' varDef - ; - -def_ - : patVarDef - | 'def' funDef - | 'type' NL* typeDef - | tmplDef - ; - -patDef - : pattern2 (',' pattern2)* (':' type_)? '=' expr - ; - -varDef - : patDef - | ids ':' type_ '=' '_' - ; - -funDef - : funSig (':' type_)? '=' expr - | funSig NL? '{' block '}' - | 'this' paramClause paramClauses ('=' constrExpr | NL? constrBlock) - ; - -typeDef - : Id typeParamClause? '=' type_ - ; - -tmplDef - : 'case'? 'class' classDef - | 'case'? 'object' objectDef - | 'trait' traitDef - ; - -classDef - : Id typeParamClause? constrAnnotation* accessModifier? classParamClauses classTemplateOpt - ; - -traitDef - : Id typeParamClause? traitTemplateOpt - ; - -objectDef - : Id classTemplateOpt - ; - -classTemplateOpt - : 'extends' classTemplate - | ('extends'? templateBody)? - ; - -traitTemplateOpt - : 'extends' traitTemplate - | ('extends'? templateBody)? - ; - -classTemplate - : earlyDefs? classParents templateBody? - ; - -traitTemplate - : earlyDefs? traitParents templateBody? - ; - -classParents - : constr ('with' annotType)* - ; - -traitParents - : annotType ('with' annotType)* - ; - -constr - : annotType argumentExprs* - ; - -earlyDefs - : '{' earlyDef+ '}' 'with' - ; - -earlyDef - : (annotation NL?)* modifier* patVarDef - ; - -constrExpr - : selfInvocation - | constrBlock - ; - -constrBlock - : '{' selfInvocation (blockStat)* '}' - ; - -selfInvocation - : 'this' argumentExprs+ - ; - -topStatSeq - : topStat+ - ; - -topStat - : (annotation NL?)* modifier* tmplDef - | import_ - | packaging - | packageObject - ; - -packaging - : 'package' qualId NL? '{' topStatSeq '}' - ; - -packageObject - : 'package' 'object' objectDef - ; - -compilationUnit - : ('package' qualId)* topStatSeq - ; - -// Lexer - -Id - : Plainid - | '`' (CharNoBackQuoteOrNewline | UnicodeEscape | CharEscapeSeq)+ '`' - ; - -BooleanLiteral - : 'true' - | 'false' - ; - -CharacterLiteral - : '\'' (PrintableChar | CharEscapeSeq) '\'' - ; - -SymbolLiteral - : '\'' Plainid - ; - -IntegerLiteral - : (DecimalNumeral | HexNumeral) ('L' | 'l')? - ; - -StringLiteral - : '"' StringElement* '"' - | '"""' MultiLineChars '"""' - ; - -FloatingPointLiteral - : Digit+ '.' Digit+ ExponentPart? FloatType? - | '.' Digit+ ExponentPart? FloatType? - | Digit ExponentPart FloatType? - | Digit+ ExponentPart? FloatType - ; - -Varid - : Lower Idrest - ; - -BoundVarid - : Varid - | '`' Varid '`' - ; - -Paren - : '(' - | ')' - | '[' - | ']' - | '{' - | '}' - ; - -Delim - : '`' - | '\'' - | '"' - | '.' - | ';' - | ',' - ; - -Semi - : (';' | (NL)+) -> skip - ; - -NL - : '\n' - | '\r' '\n'? - ; - -// \u0020-\u0026 """ !"#$%""" -// \u0028-\u007E """()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~""" -fragment CharNoBackQuoteOrNewline - : [\u0020-\u0026\u0028-\u007E] - ; - -// fragments - -fragment UnicodeEscape - : '\\' 'u' 'u'? HexDigit HexDigit HexDigit HexDigit - ; - -fragment WhiteSpace - : '\u0020' - | '\u0009' - | '\u000D' - | '\u000A' - ; - -fragment Opchar - : '!' - | '#' - | '%' - | '&' - | '*' - | '+' - | '-' - | ':' - | '<' - | '=' - | '>' - | '?' - | '@' - | '\\' - | '^' - | '|' - | '~' - ; - -fragment Op - : '/'? Opchar+ - ; - -fragment Idrest - : (Letter | Digit)* ('_' Op)? - ; - -fragment StringElement - : '\u0020' - | '\u0021' - | '\u0023' .. '\u007F' - | CharEscapeSeq - ; - -fragment MultiLineChars - : (StringElement | NL)* - ; - -fragment HexDigit - : '0' .. '9' - | 'A' .. 'F' - | 'a' .. 'f' - ; - -fragment FloatType - : 'F' - | 'f' - | 'D' - | 'd' - ; - -fragment Upper - : 'A' .. 'Z' - | '$' - | '_' - | UnicodeClass_LU - ; - -fragment Lower - : 'a' .. 'z' - | UnicodeClass_LL - ; - -fragment Letter - : Upper - | Lower - | UnicodeClass_LO - | UnicodeClass_LT // TODO Add category Nl - ; - -// and Unicode categories Lo, Lt, Nl - -fragment ExponentPart - : ('E' | 'e') ('+' | '-')? Digit+ - ; - -fragment PrintableChar - : '\u0020' .. '\u007F' - ; - -fragment PrintableCharExceptWhitespace - : '\u0021' .. '\u007F' - ; - -fragment CharEscapeSeq - : '\\' ('b' | 't' | 'n' | 'f' | 'r' | '"' | '\'' | '\\') - ; - -fragment DecimalNumeral - : '0' - | NonZeroDigit Digit* - ; - -fragment HexNumeral - : '0' 'x' HexDigit HexDigit+ - ; - -fragment Digit - : '0' - | NonZeroDigit - ; - -fragment NonZeroDigit - : '1' .. '9' - ; - -fragment VaridFragment - : Varid - ; - -fragment Plainid - : Upper Idrest - | Lower Idrest - | Op - ; - -// -// Unicode categories -// https://github.com/antlr/grammars-v4/blob/master/stringtemplate/LexUnicode.g4 -// - -fragment UnicodeLetter - : UnicodeClass_LU - | UnicodeClass_LL - | UnicodeClass_LT - | UnicodeClass_LM - | UnicodeClass_LO - ; - -fragment UnicodeClass_LU - : '\u0041' ..'\u005a' - | '\u00c0' ..'\u00d6' - | '\u00d8' ..'\u00de' - | '\u0100' ..'\u0136' - | '\u0139' ..'\u0147' - | '\u014a' ..'\u0178' - | '\u0179' ..'\u017d' - | '\u0181' ..'\u0182' - | '\u0184' ..'\u0186' - | '\u0187' ..'\u0189' - | '\u018a' ..'\u018b' - | '\u018e' ..'\u0191' - | '\u0193' ..'\u0194' - | '\u0196' ..'\u0198' - | '\u019c' ..'\u019d' - | '\u019f' ..'\u01a0' - | '\u01a2' ..'\u01a6' - | '\u01a7' ..'\u01a9' - | '\u01ac' ..'\u01ae' - | '\u01af' ..'\u01b1' - | '\u01b2' ..'\u01b3' - | '\u01b5' ..'\u01b7' - | '\u01b8' ..'\u01bc' - | '\u01c4' ..'\u01cd' - | '\u01cf' ..'\u01db' - | '\u01de' ..'\u01ee' - | '\u01f1' ..'\u01f4' - | '\u01f6' ..'\u01f8' - | '\u01fa' ..'\u0232' - | '\u023a' ..'\u023b' - | '\u023d' ..'\u023e' - | '\u0241' ..'\u0243' - | '\u0244' ..'\u0246' - | '\u0248' ..'\u024e' - | '\u0370' ..'\u0372' - | '\u0376' ..'\u037f' - | '\u0386' ..'\u0388' - | '\u0389' ..'\u038a' - | '\u038c' ..'\u038e' - | '\u038f' ..'\u0391' - | '\u0392' ..'\u03a1' - | '\u03a3' ..'\u03ab' - | '\u03cf' ..'\u03d2' - | '\u03d3' ..'\u03d4' - | '\u03d8' ..'\u03ee' - | '\u03f4' ..'\u03f7' - | '\u03f9' ..'\u03fa' - | '\u03fd' ..'\u042f' - | '\u0460' ..'\u0480' - | '\u048a' ..'\u04c0' - | '\u04c1' ..'\u04cd' - | '\u04d0' ..'\u052e' - | '\u0531' ..'\u0556' - | '\u10a0' ..'\u10c5' - | '\u10c7' ..'\u10cd' - | '\u1e00' ..'\u1e94' - | '\u1e9e' ..'\u1efe' - | '\u1f08' ..'\u1f0f' - | '\u1f18' ..'\u1f1d' - | '\u1f28' ..'\u1f2f' - | '\u1f38' ..'\u1f3f' - | '\u1f48' ..'\u1f4d' - | '\u1f59' ..'\u1f5f' - | '\u1f68' ..'\u1f6f' - | '\u1fb8' ..'\u1fbb' - | '\u1fc8' ..'\u1fcb' - | '\u1fd8' ..'\u1fdb' - | '\u1fe8' ..'\u1fec' - | '\u1ff8' ..'\u1ffb' - | '\u2102' ..'\u2107' - | '\u210b' ..'\u210d' - | '\u2110' ..'\u2112' - | '\u2115' ..'\u2119' - | '\u211a' ..'\u211d' - | '\u2124' ..'\u212a' - | '\u212b' ..'\u212d' - | '\u2130' ..'\u2133' - | '\u213e' ..'\u213f' - | '\u2145' ..'\u2183' - | '\u2c00' ..'\u2c2e' - | '\u2c60' ..'\u2c62' - | '\u2c63' ..'\u2c64' - | '\u2c67' ..'\u2c6d' - | '\u2c6e' ..'\u2c70' - | '\u2c72' ..'\u2c75' - | '\u2c7e' ..'\u2c80' - | '\u2c82' ..'\u2ce2' - | '\u2ceb' ..'\u2ced' - | '\u2cf2' ..'\ua640' - | '\ua642' ..'\ua66c' - | '\ua680' ..'\ua69a' - | '\ua722' ..'\ua72e' - | '\ua732' ..'\ua76e' - | '\ua779' ..'\ua77d' - | '\ua77e' ..'\ua786' - | '\ua78b' ..'\ua78d' - | '\ua790' ..'\ua792' - | '\ua796' ..'\ua7aa' - | '\ua7ab' ..'\ua7ad' - | '\ua7b0' ..'\ua7b1' - | '\uff21' ..'\uff3a' - ; - -fragment UnicodeClass_LL - : '\u0061' ..'\u007A' - | '\u00b5' ..'\u00df' - | '\u00e0' ..'\u00f6' - | '\u00f8' ..'\u00ff' - | '\u0101' ..'\u0137' - | '\u0138' ..'\u0148' - | '\u0149' ..'\u0177' - | '\u017a' ..'\u017e' - | '\u017f' ..'\u0180' - | '\u0183' ..'\u0185' - | '\u0188' ..'\u018c' - | '\u018d' ..'\u0192' - | '\u0195' ..'\u0199' - | '\u019a' ..'\u019b' - | '\u019e' ..'\u01a1' - | '\u01a3' ..'\u01a5' - | '\u01a8' ..'\u01aa' - | '\u01ab' ..'\u01ad' - | '\u01b0' ..'\u01b4' - | '\u01b6' ..'\u01b9' - | '\u01ba' ..'\u01bd' - | '\u01be' ..'\u01bf' - | '\u01c6' ..'\u01cc' - | '\u01ce' ..'\u01dc' - | '\u01dd' ..'\u01ef' - | '\u01f0' ..'\u01f3' - | '\u01f5' ..'\u01f9' - | '\u01fb' ..'\u0233' - | '\u0234' ..'\u0239' - | '\u023c' ..'\u023f' - | '\u0240' ..'\u0242' - | '\u0247' ..'\u024f' - | '\u0250' ..'\u0293' - | '\u0295' ..'\u02af' - | '\u0371' ..'\u0373' - | '\u0377' ..'\u037b' - | '\u037c' ..'\u037d' - | '\u0390' ..'\u03ac' - | '\u03ad' ..'\u03ce' - | '\u03d0' ..'\u03d1' - | '\u03d5' ..'\u03d7' - | '\u03d9' ..'\u03ef' - | '\u03f0' ..'\u03f3' - | '\u03f5' ..'\u03fb' - | '\u03fc' ..'\u0430' - | '\u0431' ..'\u045f' - | '\u0461' ..'\u0481' - | '\u048b' ..'\u04bf' - | '\u04c2' ..'\u04ce' - | '\u04cf' ..'\u052f' - | '\u0561' ..'\u0587' - | '\u1d00' ..'\u1d2b' - | '\u1d6b' ..'\u1d77' - | '\u1d79' ..'\u1d9a' - | '\u1e01' ..'\u1e95' - | '\u1e96' ..'\u1e9d' - | '\u1e9f' ..'\u1eff' - | '\u1f00' ..'\u1f07' - | '\u1f10' ..'\u1f15' - | '\u1f20' ..'\u1f27' - | '\u1f30' ..'\u1f37' - | '\u1f40' ..'\u1f45' - | '\u1f50' ..'\u1f57' - | '\u1f60' ..'\u1f67' - | '\u1f70' ..'\u1f7d' - | '\u1f80' ..'\u1f87' - | '\u1f90' ..'\u1f97' - | '\u1fa0' ..'\u1fa7' - | '\u1fb0' ..'\u1fb4' - | '\u1fb6' ..'\u1fb7' - | '\u1fbe' ..'\u1fc2' - | '\u1fc3' ..'\u1fc4' - | '\u1fc6' ..'\u1fc7' - | '\u1fd0' ..'\u1fd3' - | '\u1fd6' ..'\u1fd7' - | '\u1fe0' ..'\u1fe7' - | '\u1ff2' ..'\u1ff4' - | '\u1ff6' ..'\u1ff7' - | '\u210a' ..'\u210e' - | '\u210f' ..'\u2113' - | '\u212f' ..'\u2139' - | '\u213c' ..'\u213d' - | '\u2146' ..'\u2149' - | '\u214e' ..'\u2184' - | '\u2c30' ..'\u2c5e' - | '\u2c61' ..'\u2c65' - | '\u2c66' ..'\u2c6c' - | '\u2c71' ..'\u2c73' - | '\u2c74' ..'\u2c76' - | '\u2c77' ..'\u2c7b' - | '\u2c81' ..'\u2ce3' - | '\u2ce4' ..'\u2cec' - | '\u2cee' ..'\u2cf3' - | '\u2d00' ..'\u2d25' - | '\u2d27' ..'\u2d2d' - | '\ua641' ..'\ua66d' - | '\ua681' ..'\ua69b' - | '\ua723' ..'\ua72f' - | '\ua730' ..'\ua731' - | '\ua733' ..'\ua771' - | '\ua772' ..'\ua778' - | '\ua77a' ..'\ua77c' - | '\ua77f' ..'\ua787' - | '\ua78c' ..'\ua78e' - | '\ua791' ..'\ua793' - | '\ua794' ..'\ua795' - | '\ua797' ..'\ua7a9' - | '\ua7fa' ..'\uab30' - | '\uab31' ..'\uab5a' - | '\uab64' ..'\uab65' - | '\ufb00' ..'\ufb06' - | '\ufb13' ..'\ufb17' - | '\uff41' ..'\uff5a' - ; - -fragment UnicodeClass_LT - : '\u01c5' ..'\u01cb' - | '\u01f2' ..'\u1f88' - | '\u1f89' ..'\u1f8f' - | '\u1f98' ..'\u1f9f' - | '\u1fa8' ..'\u1faf' - | '\u1fbc' ..'\u1fcc' - | '\u1ffc' ..'\u1ffc' - ; - -fragment UnicodeClass_LM - : '\u02b0' ..'\u02c1' - | '\u02c6' ..'\u02d1' - | '\u02e0' ..'\u02e4' - | '\u02ec' ..'\u02ee' - | '\u0374' ..'\u037a' - | '\u0559' ..'\u0640' - | '\u06e5' ..'\u06e6' - | '\u07f4' ..'\u07f5' - | '\u07fa' ..'\u081a' - | '\u0824' ..'\u0828' - | '\u0971' ..'\u0e46' - | '\u0ec6' ..'\u10fc' - | '\u17d7' ..'\u1843' - | '\u1aa7' ..'\u1c78' - | '\u1c79' ..'\u1c7d' - | '\u1d2c' ..'\u1d6a' - | '\u1d78' ..'\u1d9b' - | '\u1d9c' ..'\u1dbf' - | '\u2071' ..'\u207f' - | '\u2090' ..'\u209c' - | '\u2c7c' ..'\u2c7d' - | '\u2d6f' ..'\u2e2f' - | '\u3005' ..'\u3031' - | '\u3032' ..'\u3035' - | '\u303b' ..'\u309d' - | '\u309e' ..'\u30fc' - | '\u30fd' ..'\u30fe' - | '\ua015' ..'\ua4f8' - | '\ua4f9' ..'\ua4fd' - | '\ua60c' ..'\ua67f' - | '\ua69c' ..'\ua69d' - | '\ua717' ..'\ua71f' - | '\ua770' ..'\ua788' - | '\ua7f8' ..'\ua7f9' - | '\ua9cf' ..'\ua9e6' - | '\uaa70' ..'\uaadd' - | '\uaaf3' ..'\uaaf4' - | '\uab5c' ..'\uab5f' - | '\uff70' ..'\uff9e' - | '\uff9f' ..'\uff9f' - ; - -fragment UnicodeClass_LO - : '\u00aa' ..'\u00ba' - | '\u01bb' ..'\u01c0' - | '\u01c1' ..'\u01c3' - | '\u0294' ..'\u05d0' - | '\u05d1' ..'\u05ea' - | '\u05f0' ..'\u05f2' - | '\u0620' ..'\u063f' - | '\u0641' ..'\u064a' - | '\u066e' ..'\u066f' - | '\u0671' ..'\u06d3' - | '\u06d5' ..'\u06ee' - | '\u06ef' ..'\u06fa' - | '\u06fb' ..'\u06fc' - | '\u06ff' ..'\u0710' - | '\u0712' ..'\u072f' - | '\u074d' ..'\u07a5' - | '\u07b1' ..'\u07ca' - | '\u07cb' ..'\u07ea' - | '\u0800' ..'\u0815' - | '\u0840' ..'\u0858' - | '\u08a0' ..'\u08b2' - | '\u0904' ..'\u0939' - | '\u093d' ..'\u0950' - | '\u0958' ..'\u0961' - | '\u0972' ..'\u0980' - | '\u0985' ..'\u098c' - | '\u098f' ..'\u0990' - | '\u0993' ..'\u09a8' - | '\u09aa' ..'\u09b0' - | '\u09b2' ..'\u09b6' - | '\u09b7' ..'\u09b9' - | '\u09bd' ..'\u09ce' - | '\u09dc' ..'\u09dd' - | '\u09df' ..'\u09e1' - | '\u09f0' ..'\u09f1' - | '\u0a05' ..'\u0a0a' - | '\u0a0f' ..'\u0a10' - | '\u0a13' ..'\u0a28' - | '\u0a2a' ..'\u0a30' - | '\u0a32' ..'\u0a33' - | '\u0a35' ..'\u0a36' - | '\u0a38' ..'\u0a39' - | '\u0a59' ..'\u0a5c' - | '\u0a5e' ..'\u0a72' - | '\u0a73' ..'\u0a74' - | '\u0a85' ..'\u0a8d' - | '\u0a8f' ..'\u0a91' - | '\u0a93' ..'\u0aa8' - | '\u0aaa' ..'\u0ab0' - | '\u0ab2' ..'\u0ab3' - | '\u0ab5' ..'\u0ab9' - | '\u0abd' ..'\u0ad0' - | '\u0ae0' ..'\u0ae1' - | '\u0b05' ..'\u0b0c' - | '\u0b0f' ..'\u0b10' - | '\u0b13' ..'\u0b28' - | '\u0b2a' ..'\u0b30' - | '\u0b32' ..'\u0b33' - | '\u0b35' ..'\u0b39' - | '\u0b3d' ..'\u0b5c' - | '\u0b5d' ..'\u0b5f' - | '\u0b60' ..'\u0b61' - | '\u0b71' ..'\u0b83' - | '\u0b85' ..'\u0b8a' - | '\u0b8e' ..'\u0b90' - | '\u0b92' ..'\u0b95' - | '\u0b99' ..'\u0b9a' - | '\u0b9c' ..'\u0b9e' - | '\u0b9f' ..'\u0ba3' - | '\u0ba4' ..'\u0ba8' - | '\u0ba9' ..'\u0baa' - | '\u0bae' ..'\u0bb9' - | '\u0bd0' ..'\u0c05' - | '\u0c06' ..'\u0c0c' - | '\u0c0e' ..'\u0c10' - | '\u0c12' ..'\u0c28' - | '\u0c2a' ..'\u0c39' - | '\u0c3d' ..'\u0c58' - | '\u0c59' ..'\u0c60' - | '\u0c61' ..'\u0c85' - | '\u0c86' ..'\u0c8c' - | '\u0c8e' ..'\u0c90' - | '\u0c92' ..'\u0ca8' - | '\u0caa' ..'\u0cb3' - | '\u0cb5' ..'\u0cb9' - | '\u0cbd' ..'\u0cde' - | '\u0ce0' ..'\u0ce1' - | '\u0cf1' ..'\u0cf2' - | '\u0d05' ..'\u0d0c' - | '\u0d0e' ..'\u0d10' - | '\u0d12' ..'\u0d3a' - | '\u0d3d' ..'\u0d4e' - | '\u0d60' ..'\u0d61' - | '\u0d7a' ..'\u0d7f' - | '\u0d85' ..'\u0d96' - | '\u0d9a' ..'\u0db1' - | '\u0db3' ..'\u0dbb' - | '\u0dbd' ..'\u0dc0' - | '\u0dc1' ..'\u0dc6' - | '\u0e01' ..'\u0e30' - | '\u0e32' ..'\u0e33' - | '\u0e40' ..'\u0e45' - | '\u0e81' ..'\u0e82' - | '\u0e84' ..'\u0e87' - | '\u0e88' ..'\u0e8a' - | '\u0e8d' ..'\u0e94' - | '\u0e95' ..'\u0e97' - | '\u0e99' ..'\u0e9f' - | '\u0ea1' ..'\u0ea3' - | '\u0ea5' ..'\u0ea7' - | '\u0eaa' ..'\u0eab' - | '\u0ead' ..'\u0eb0' - | '\u0eb2' ..'\u0eb3' - | '\u0ebd' ..'\u0ec0' - | '\u0ec1' ..'\u0ec4' - | '\u0edc' ..'\u0edf' - | '\u0f00' ..'\u0f40' - | '\u0f41' ..'\u0f47' - | '\u0f49' ..'\u0f6c' - | '\u0f88' ..'\u0f8c' - | '\u1000' ..'\u102a' - | '\u103f' ..'\u1050' - | '\u1051' ..'\u1055' - | '\u105a' ..'\u105d' - | '\u1061' ..'\u1065' - | '\u1066' ..'\u106e' - | '\u106f' ..'\u1070' - | '\u1075' ..'\u1081' - | '\u108e' ..'\u10d0' - | '\u10d1' ..'\u10fa' - | '\u10fd' ..'\u1248' - | '\u124a' ..'\u124d' - | '\u1250' ..'\u1256' - | '\u1258' ..'\u125a' - | '\u125b' ..'\u125d' - | '\u1260' ..'\u1288' - | '\u128a' ..'\u128d' - | '\u1290' ..'\u12b0' - | '\u12b2' ..'\u12b5' - | '\u12b8' ..'\u12be' - | '\u12c0' ..'\u12c2' - | '\u12c3' ..'\u12c5' - | '\u12c8' ..'\u12d6' - | '\u12d8' ..'\u1310' - | '\u1312' ..'\u1315' - | '\u1318' ..'\u135a' - | '\u1380' ..'\u138f' - | '\u13a0' ..'\u13f4' - | '\u1401' ..'\u166c' - | '\u166f' ..'\u167f' - | '\u1681' ..'\u169a' - | '\u16a0' ..'\u16ea' - | '\u16f1' ..'\u16f8' - | '\u1700' ..'\u170c' - | '\u170e' ..'\u1711' - | '\u1720' ..'\u1731' - | '\u1740' ..'\u1751' - | '\u1760' ..'\u176c' - | '\u176e' ..'\u1770' - | '\u1780' ..'\u17b3' - | '\u17dc' ..'\u1820' - | '\u1821' ..'\u1842' - | '\u1844' ..'\u1877' - | '\u1880' ..'\u18a8' - | '\u18aa' ..'\u18b0' - | '\u18b1' ..'\u18f5' - | '\u1900' ..'\u191e' - | '\u1950' ..'\u196d' - | '\u1970' ..'\u1974' - | '\u1980' ..'\u19ab' - | '\u19c1' ..'\u19c7' - | '\u1a00' ..'\u1a16' - | '\u1a20' ..'\u1a54' - | '\u1b05' ..'\u1b33' - | '\u1b45' ..'\u1b4b' - | '\u1b83' ..'\u1ba0' - | '\u1bae' ..'\u1baf' - | '\u1bba' ..'\u1be5' - | '\u1c00' ..'\u1c23' - | '\u1c4d' ..'\u1c4f' - | '\u1c5a' ..'\u1c77' - | '\u1ce9' ..'\u1cec' - | '\u1cee' ..'\u1cf1' - | '\u1cf5' ..'\u1cf6' - | '\u2135' ..'\u2138' - | '\u2d30' ..'\u2d67' - | '\u2d80' ..'\u2d96' - | '\u2da0' ..'\u2da6' - | '\u2da8' ..'\u2dae' - | '\u2db0' ..'\u2db6' - | '\u2db8' ..'\u2dbe' - | '\u2dc0' ..'\u2dc6' - | '\u2dc8' ..'\u2dce' - | '\u2dd0' ..'\u2dd6' - | '\u2dd8' ..'\u2dde' - | '\u3006' ..'\u303c' - | '\u3041' ..'\u3096' - | '\u309f' ..'\u30a1' - | '\u30a2' ..'\u30fa' - | '\u30ff' ..'\u3105' - | '\u3106' ..'\u312d' - | '\u3131' ..'\u318e' - | '\u31a0' ..'\u31ba' - | '\u31f0' ..'\u31ff' - | '\u3400' ..'\u4db5' - | '\u4e00' ..'\u9fcc' - | '\ua000' ..'\ua014' - | '\ua016' ..'\ua48c' - | '\ua4d0' ..'\ua4f7' - | '\ua500' ..'\ua60b' - | '\ua610' ..'\ua61f' - | '\ua62a' ..'\ua62b' - | '\ua66e' ..'\ua6a0' - | '\ua6a1' ..'\ua6e5' - | '\ua7f7' ..'\ua7fb' - | '\ua7fc' ..'\ua801' - | '\ua803' ..'\ua805' - | '\ua807' ..'\ua80a' - | '\ua80c' ..'\ua822' - | '\ua840' ..'\ua873' - | '\ua882' ..'\ua8b3' - | '\ua8f2' ..'\ua8f7' - | '\ua8fb' ..'\ua90a' - | '\ua90b' ..'\ua925' - | '\ua930' ..'\ua946' - | '\ua960' ..'\ua97c' - | '\ua984' ..'\ua9b2' - | '\ua9e0' ..'\ua9e4' - | '\ua9e7' ..'\ua9ef' - | '\ua9fa' ..'\ua9fe' - | '\uaa00' ..'\uaa28' - | '\uaa40' ..'\uaa42' - | '\uaa44' ..'\uaa4b' - | '\uaa60' ..'\uaa6f' - | '\uaa71' ..'\uaa76' - | '\uaa7a' ..'\uaa7e' - | '\uaa7f' ..'\uaaaf' - | '\uaab1' ..'\uaab5' - | '\uaab6' ..'\uaab9' - | '\uaaba' ..'\uaabd' - | '\uaac0' ..'\uaac2' - | '\uaadb' ..'\uaadc' - | '\uaae0' ..'\uaaea' - | '\uaaf2' ..'\uab01' - | '\uab02' ..'\uab06' - | '\uab09' ..'\uab0e' - | '\uab11' ..'\uab16' - | '\uab20' ..'\uab26' - | '\uab28' ..'\uab2e' - | '\uabc0' ..'\uabe2' - | '\uac00' ..'\ud7a3' - | '\ud7b0' ..'\ud7c6' - | '\ud7cb' ..'\ud7fb' - | '\uf900' ..'\ufa6d' - | '\ufa70' ..'\ufad9' - | '\ufb1d' ..'\ufb1f' - | '\ufb20' ..'\ufb28' - | '\ufb2a' ..'\ufb36' - | '\ufb38' ..'\ufb3c' - | '\ufb3e' ..'\ufb40' - | '\ufb41' ..'\ufb43' - | '\ufb44' ..'\ufb46' - | '\ufb47' ..'\ufbb1' - | '\ufbd3' ..'\ufd3d' - | '\ufd50' ..'\ufd8f' - | '\ufd92' ..'\ufdc7' - | '\ufdf0' ..'\ufdfb' - | '\ufe70' ..'\ufe74' - | '\ufe76' ..'\ufefc' - | '\uff66' ..'\uff6f' - | '\uff71' ..'\uff9d' - | '\uffa0' ..'\uffbe' - | '\uffc2' ..'\uffc7' - | '\uffca' ..'\uffcf' - | '\uffd2' ..'\uffd7' - | '\uffda' ..'\uffdc' - ; - -fragment UnicodeDigit // UnicodeClass_ND - : '\u0030' ..'\u0039' - | '\u0660' ..'\u0669' - | '\u06f0' ..'\u06f9' - | '\u07c0' ..'\u07c9' - | '\u0966' ..'\u096f' - | '\u09e6' ..'\u09ef' - | '\u0a66' ..'\u0a6f' - | '\u0ae6' ..'\u0aef' - | '\u0b66' ..'\u0b6f' - | '\u0be6' ..'\u0bef' - | '\u0c66' ..'\u0c6f' - | '\u0ce6' ..'\u0cef' - | '\u0d66' ..'\u0d6f' - | '\u0de6' ..'\u0def' - | '\u0e50' ..'\u0e59' - | '\u0ed0' ..'\u0ed9' - | '\u0f20' ..'\u0f29' - | '\u1040' ..'\u1049' - | '\u1090' ..'\u1099' - | '\u17e0' ..'\u17e9' - | '\u1810' ..'\u1819' - | '\u1946' ..'\u194f' - | '\u19d0' ..'\u19d9' - | '\u1a80' ..'\u1a89' - | '\u1a90' ..'\u1a99' - | '\u1b50' ..'\u1b59' - | '\u1bb0' ..'\u1bb9' - | '\u1c40' ..'\u1c49' - | '\u1c50' ..'\u1c59' - | '\ua620' ..'\ua629' - | '\ua8d0' ..'\ua8d9' - | '\ua900' ..'\ua909' - | '\ua9d0' ..'\ua9d9' - | '\ua9f0' ..'\ua9f9' - | '\uaa50' ..'\uaa59' - | '\uabf0' ..'\uabf9' - | '\uff10' ..'\uff19' - ; - -// -// Whitespace and comments -// -NEWLINE - : NL+ -> skip - ; - -WS - : WhiteSpace+ -> skip - ; - -COMMENT - : '/*' (COMMENT | .)* '*/' -> skip - ; - -LINE_COMMENT - : '//' (~[\r\n])* -> skip - ; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptLexer.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptLexer.g4 deleted file mode 100644 index b15a8d41..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptLexer.g4 +++ /dev/null @@ -1,315 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers (original author) and Alexandre Vitorelli (contributor -> ported to CSharp) - * Copyright (c) 2017 by Ivan Kochurkin (Positive Technologies): - added ECMAScript 6 support, cleared and transformed to the universal grammar. - * Copyright (c) 2018 by Juan Alvarez (contributor -> ported to Go) - * Copyright (c) 2019 by Andrii Artiushok (contributor -> added TypeScript support) - * Copyright (c) 2024 by Andrew Leppard (www.wegrok.review) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - -lexer grammar TypeScriptLexer; - -channels { - ERROR -} - -options { - superClass = TypeScriptLexerBase; -} - -MultiLineComment : '/*' .*? '*/' -> channel(HIDDEN); -SingleLineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN); -RegularExpressionLiteral: - '/' RegularExpressionFirstChar RegularExpressionChar* {this.IsRegexPossible()}? '/' IdentifierPart* -; - -OpenBracket : '['; -CloseBracket : ']'; -OpenParen : '('; -CloseParen : ')'; -OpenBrace : '{' {this.ProcessOpenBrace();}; -TemplateCloseBrace : {this.IsInTemplateString()}? '}' -> popMode; -CloseBrace : '}' {this.ProcessCloseBrace();}; -SemiColon : ';'; -Comma : ','; -Assign : '='; -QuestionMark : '?'; -QuestionMarkDot : '?.'; -Colon : ':'; -Ellipsis : '...'; -Dot : '.'; -PlusPlus : '++'; -MinusMinus : '--'; -Plus : '+'; -Minus : '-'; -BitNot : '~'; -Not : '!'; -Multiply : '*'; -Divide : '/'; -Modulus : '%'; -Power : '**'; -NullCoalesce : '??'; -Hashtag : '#'; -LeftShiftArithmetic : '<<'; -// We can't match these in the lexer because it would cause issues when parsing -// types like Map> -// RightShiftArithmetic : '>>'; -// RightShiftLogical : '>>>'; -LessThan : '<'; -MoreThan : '>'; -LessThanEquals : '<='; -GreaterThanEquals : '>='; -Equals_ : '=='; -NotEquals : '!='; -IdentityEquals : '==='; -IdentityNotEquals : '!=='; -BitAnd : '&'; -BitXOr : '^'; -BitOr : '|'; -And : '&&'; -Or : '||'; -MultiplyAssign : '*='; -DivideAssign : '/='; -ModulusAssign : '%='; -PlusAssign : '+='; -MinusAssign : '-='; -LeftShiftArithmeticAssign : '<<='; -RightShiftArithmeticAssign : '>>='; -RightShiftLogicalAssign : '>>>='; -BitAndAssign : '&='; -BitXorAssign : '^='; -BitOrAssign : '|='; -PowerAssign : '**='; -NullishCoalescingAssign : '??='; -ARROW : '=>'; - -/// Null Literals - -NullLiteral: 'null'; - -/// Boolean Literals - -BooleanLiteral: 'true' | 'false'; - -/// Numeric Literals - -DecimalLiteral: - DecimalIntegerLiteral '.' [0-9] [0-9_]* ExponentPart? - | '.' [0-9] [0-9_]* ExponentPart? - | DecimalIntegerLiteral ExponentPart? -; - -/// Numeric Literals - -HexIntegerLiteral : '0' [xX] [0-9a-fA-F] HexDigit*; -OctalIntegerLiteral : '0' [0-7]+ {!this.IsStrictMode()}?; -OctalIntegerLiteral2 : '0' [oO] [0-7] [_0-7]*; -BinaryIntegerLiteral : '0' [bB] [01] [_01]*; - -BigHexIntegerLiteral : '0' [xX] [0-9a-fA-F] HexDigit* 'n'; -BigOctalIntegerLiteral : '0' [oO] [0-7] [_0-7]* 'n'; -BigBinaryIntegerLiteral : '0' [bB] [01] [_01]* 'n'; -BigDecimalIntegerLiteral : DecimalIntegerLiteral 'n'; - -/// Keywords - -Break : 'break'; -Do : 'do'; -Instanceof : 'instanceof'; -Typeof : 'typeof'; -Case : 'case'; -Else : 'else'; -New : 'new'; -Var : 'var'; -Catch : 'catch'; -Finally : 'finally'; -Return : 'return'; -Void : 'void'; -Continue : 'continue'; -For : 'for'; -Switch : 'switch'; -While : 'while'; -Debugger : 'debugger'; -Function_ : 'function'; -This : 'this'; -With : 'with'; -Default : 'default'; -If : 'if'; -Throw : 'throw'; -Delete : 'delete'; -In : 'in'; -Try : 'try'; -As : 'as'; -From : 'from'; -ReadOnly : 'readonly'; -Async : 'async'; -Await : 'await'; -Yield : 'yield'; -YieldStar : 'yield*'; - -/// Future Reserved Words - -Class : 'class'; -Enum : 'enum'; -Extends : 'extends'; -Super : 'super'; -Const : 'const'; -Export : 'export'; -Import : 'import'; - -/// The following tokens are also considered to be FutureReservedWords -/// when parsing strict mode - -Implements : 'implements'; -Let : 'let'; -Private : 'private'; -Public : 'public'; -Interface : 'interface'; -Package : 'package'; -Protected : 'protected'; -Static : 'static'; - -//keywords: -Any : 'any'; -Number : 'number'; -Never : 'never'; -Boolean : 'boolean'; -String : 'string'; -Unique : 'unique'; -Symbol : 'symbol'; -Undefined : 'undefined'; -Object : 'object'; - -Of : 'of'; -KeyOf : 'keyof'; - -TypeAlias: 'type'; - -Constructor : 'constructor'; -Namespace : 'namespace'; -Require : 'require'; -Module : 'module'; -Declare : 'declare'; - -Abstract: 'abstract'; - -Is: 'is'; - -// -// Ext.2 Additions to 1.8: Decorators -// -At: '@'; - -/// Identifier Names and Identifiers - -Identifier: IdentifierStart IdentifierPart*; - -/// String Literals -StringLiteral: - ('"' DoubleStringCharacter* '"' | '\'' SingleStringCharacter* '\'') {this.ProcessStringLiteral();} -; - -BackTick: '`' {this.IncreaseTemplateDepth();} -> pushMode(TEMPLATE); - -WhiteSpaces: [\t\u000B\u000C\u0020\u00A0]+ -> channel(HIDDEN); - -LineTerminator: [\r\n\u2028\u2029] -> channel(HIDDEN); - -/// Comments - -HtmlComment : '' -> channel(HIDDEN); -CDataComment : '' -> channel(HIDDEN); -UnexpectedCharacter : . -> channel(ERROR); - -mode TEMPLATE; - -TemplateStringEscapeAtom : '\\' .; -BackTickInside : '`' {this.DecreaseTemplateDepth();} -> type(BackTick), popMode; -TemplateStringStartExpression : '${' {this.StartTemplateString();} -> pushMode(DEFAULT_MODE); -TemplateStringAtom : ~[`\\]; - -// Fragment rules - -fragment DoubleStringCharacter: ~["\\\r\n] | '\\' EscapeSequence | LineContinuation; - -fragment SingleStringCharacter: ~['\\\r\n] | '\\' EscapeSequence | LineContinuation; - -fragment EscapeSequence: - CharacterEscapeSequence - | '0' // no digit ahead! TODO - | HexEscapeSequence - | UnicodeEscapeSequence - | ExtendedUnicodeEscapeSequence -; - -fragment CharacterEscapeSequence: SingleEscapeCharacter | NonEscapeCharacter; - -fragment HexEscapeSequence: 'x' HexDigit HexDigit; - -fragment UnicodeEscapeSequence: - 'u' HexDigit HexDigit HexDigit HexDigit - | 'u' '{' HexDigit HexDigit+ '}' -; - -fragment ExtendedUnicodeEscapeSequence: 'u' '{' HexDigit+ '}'; - -fragment SingleEscapeCharacter: ['"\\bfnrtv]; - -fragment NonEscapeCharacter: ~['"\\bfnrtv0-9xu\r\n]; - -fragment EscapeCharacter: SingleEscapeCharacter | [0-9] | [xu]; - -fragment LineContinuation: '\\' [\r\n\u2028\u2029]+; - -fragment HexDigit: [_0-9a-fA-F]; - -fragment DecimalIntegerLiteral: '0' | [1-9] [0-9_]*; - -fragment ExponentPart: [eE] [+-]? [0-9_]+; - -fragment IdentifierPart: IdentifierStart | [\p{Mn}] | [\p{Nd}] | [\p{Pc}] | '\u200C' | '\u200D'; - -fragment IdentifierStart: [\p{L}] | [$_] | '\\' UnicodeEscapeSequence; - -fragment RegularExpressionFirstChar: - ~[*\r\n\u2028\u2029\\/[] - | RegularExpressionBackslashSequence - | '[' RegularExpressionClassChar* ']' -; - -fragment RegularExpressionChar: - ~[\r\n\u2028\u2029\\/[] - | RegularExpressionBackslashSequence - | '[' RegularExpressionClassChar* ']' -; - -fragment RegularExpressionClassChar: ~[\r\n\u2028\u2029\]\\] | RegularExpressionBackslashSequence; - -fragment RegularExpressionBackslashSequence: '\\' ~[\r\n\u2028\u2029]; \ No newline at end of file diff --git a/src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptParser.g4 b/src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptParser.g4 deleted file mode 100644 index 4331162f..00000000 --- a/src/main/antlr4/io/github/randomcodespace/iq/grammar/typescript/TypeScriptParser.g4 +++ /dev/null @@ -1,984 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers (original author) and Alexandre Vitorelli (contributor -> ported to CSharp) - * Copyright (c) 2017 by Ivan Kochurkin (Positive Technologies): - added ECMAScript 6 support, cleared and transformed to the universal grammar. - * Copyright (c) 2018 by Juan Alvarez (contributor -> ported to Go) - * Copyright (c) 2019 by Andrii Artiushok (contributor -> added TypeScript support) - * Copyright (c) 2024 by Andrew Leppard (www.wegrok.review) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - -parser grammar TypeScriptParser; - -options { - tokenVocab = TypeScriptLexer; - superClass = TypeScriptParserBase; -} - -// SupportSyntax - -initializer - : '=' singleExpression - ; - -bindingPattern - : (arrayLiteral | objectLiteral) - ; - -// TypeScript SPart -// A.1 Types -typeParameters - : '<' typeParameterList? '>' - ; - -typeParameterList - : typeParameter (',' typeParameter)* - ; - -typeParameter - : identifier constraint? - | identifier '=' typeArgument - | typeParameters - ; - -constraint - : 'extends' type_ - ; - -typeArguments - : '<' typeArgumentList? '>' - ; - -typeArgumentList - : typeArgument (',' typeArgument)* - ; - -typeArgument - : type_ - ; - -// Union and intersection types can have a leading '|' or '&' -// See https://github.com/microsoft/TypeScript/pull/12386 -type_ - : ('|' | '&')? unionOrIntersectionOrPrimaryType - | functionType - | constructorType - | typeGeneric - ; - -unionOrIntersectionOrPrimaryType - : unionOrIntersectionOrPrimaryType '|' unionOrIntersectionOrPrimaryType # Union - | unionOrIntersectionOrPrimaryType '&' unionOrIntersectionOrPrimaryType # Intersection - | primaryType # Primary - ; - -primaryType - : '(' type_ ')' # ParenthesizedPrimType - | predefinedType # PredefinedPrimType - | typeReference # ReferencePrimType - | objectType # ObjectPrimType - | primaryType {this.notLineTerminator()}? '[' primaryType? ']' # ArrayPrimType - | '[' tupleElementTypes ']' # TuplePrimType - | typeQuery # QueryPrimType - | This # ThisPrimType - | typeReference Is primaryType # RedefinitionOfType - | KeyOf primaryType # KeyOfType - ; - -predefinedType - : Any - | NullLiteral - | Number - | DecimalLiteral - | Boolean - | BooleanLiteral - | String - | StringLiteral - | Unique? Symbol - | Never - | Undefined - | Object - | Void - ; - -typeReference - : typeName typeGeneric? - ; - -typeGeneric - : '<' typeArgumentList typeGeneric?'>' - ; - -typeName - : identifier - | namespaceName - ; - -objectType - : '{' typeBody? '}' - ; - -typeBody - : typeMemberList (SemiColon | ',')? - ; - -typeMemberList - : typeMember ((SemiColon | ',') typeMember)* - ; - -typeMember - : propertySignatur - | callSignature - | constructSignature - | indexSignature - | methodSignature ('=>' type_)? - ; - -arrayType - : primaryType {this.notLineTerminator()}? '[' ']' - ; - -tupleType - : '[' tupleElementTypes ']' - ; - -// Tuples can have a trailing comma. See https://github.com/Microsoft/TypeScript/issues/28893 -tupleElementTypes - : type_ (',' type_)* ','? - ; - -functionType - : typeParameters? '(' parameterList? ')' '=>' type_ - ; - -constructorType - : 'new' typeParameters? '(' parameterList? ')' '=>' type_ - ; - -typeQuery - : 'typeof' typeQueryExpression - ; - -typeQueryExpression - : identifier - | (identifierName '.')+ identifierName - ; - -propertySignatur - : ReadOnly? propertyName '?'? typeAnnotation? ('=>' type_)? - ; - -typeAnnotation - : ':' type_ - ; - -callSignature - : typeParameters? '(' parameterList? ')' typeAnnotation? - ; - -// Function parameter list can have a trailing comma. -// See https://github.com/Microsoft/TypeScript/issues/16152 -parameterList - : restParameter - | parameter (',' parameter)* (',' restParameter)? ','? - ; - -requiredParameterList - : requiredParameter (',' requiredParameter)* - ; - -parameter - : requiredParameter - | optionalParameter - ; - -optionalParameter - : decoratorList? ( - accessibilityModifier? identifierOrPattern ( - '?' typeAnnotation? - | typeAnnotation? initializer - ) - ) - ; - -restParameter - : '...' singleExpression typeAnnotation? - ; - -requiredParameter - : decoratorList? accessibilityModifier? identifierOrPattern typeAnnotation? - ; - -accessibilityModifier - : Public - | Private - | Protected - ; - -identifierOrPattern - : identifierName - | bindingPattern - ; - -constructSignature - : 'new' typeParameters? '(' parameterList? ')' typeAnnotation? - ; - -indexSignature - : '[' identifier ':' (Number | String) ']' typeAnnotation - ; - -methodSignature - : propertyName '?'? callSignature - ; - -typeAliasDeclaration - : Export? 'type' identifier typeParameters? '=' type_ eos - ; - -constructorDeclaration - : accessibilityModifier? Constructor '(' formalParameterList? ')' ( - ('{' functionBody '}') - | SemiColon - )? - ; - -// A.5 Interface - -interfaceDeclaration - : Export? Declare? Interface identifier typeParameters? interfaceExtendsClause? objectType SemiColon? - ; - -interfaceExtendsClause - : Extends classOrInterfaceTypeList - ; - -classOrInterfaceTypeList - : typeReference (',' typeReference)* - ; - -// A.7 Interface - -enumDeclaration - : Const? Enum identifier '{' enumBody? '}' - ; - -enumBody - : enumMemberList ','? - ; - -enumMemberList - : enumMember (',' enumMember)* - ; - -enumMember - : propertyName ('=' singleExpression)? - ; - -// A.8 Namespaces - -namespaceDeclaration - : Declare? Namespace namespaceName '{' statementList? '}' - ; - -namespaceName - : identifier ('.'+ identifier)* - ; - -importAliasDeclaration - : identifier '=' namespaceName SemiColon - ; - -// Ext.2 Additions to 1.8: Decorators - -decoratorList - : decorator+ - ; - -decorator - : '@' (decoratorMemberExpression | decoratorCallExpression) - ; - -decoratorMemberExpression - : identifier - | decoratorMemberExpression '.' identifierName - | '(' singleExpression ')' - ; - -decoratorCallExpression - : decoratorMemberExpression arguments - ; - -// ECMAPart -program - : sourceElements? EOF - ; - -sourceElement - : Export? statement - ; - -statement - : block - | variableStatement - | importStatement - | exportStatement - | emptyStatement_ - | abstractDeclaration //ADDED - | classDeclaration - | functionDeclaration - | expressionStatement - | interfaceDeclaration //ADDED - | namespaceDeclaration //ADDED - | ifStatement - | iterationStatement - | continueStatement - | breakStatement - | returnStatement - | yieldStatement - | withStatement - | labelledStatement - | switchStatement - | throwStatement - | tryStatement - | debuggerStatement - | arrowFunctionDeclaration - | generatorFunctionDeclaration - | typeAliasDeclaration //ADDED - | enumDeclaration //ADDED - | Export statement - ; - -block - : '{' statementList? '}' - ; - -statementList - : statement+ - ; - -abstractDeclaration - : Abstract (identifier callSignature | variableStatement) eos - ; - -importStatement - : Import importFromBlock - ; - -importFromBlock - : importDefault? (importNamespace | importModuleItems) importFrom eos - | StringLiteral eos - ; - -importModuleItems - : '{' (importAliasName ',')* (importAliasName ','?)? '}' - ; - -importAliasName - : moduleExportName (As importedBinding)? - ; - -moduleExportName - : identifierName - | StringLiteral - ; - -// yield and await are permitted as BindingIdentifier in the grammar -importedBinding - : Identifier - | Yield - | Await - ; - -importDefault - : aliasName ',' - ; - -importNamespace - : ('*' | identifierName) (As identifierName)? - ; - -importFrom - : From StringLiteral - ; - -aliasName - : identifierName (As identifierName)? - ; - -exportStatement - : Export Default? (exportFromBlock | declaration) eos # ExportDeclaration - | Export Default singleExpression eos # ExportDefaultDeclaration - ; - -exportFromBlock - : importNamespace importFrom eos - | exportModuleItems importFrom? eos - ; - -exportModuleItems - : '{' (exportAliasName ',')* (exportAliasName ','?)? '}' - ; - -exportAliasName - : moduleExportName (As moduleExportName)? - ; - -declaration - : variableStatement - | classDeclaration - | functionDeclaration - ; - -variableStatement - : bindingPattern typeAnnotation? initializer SemiColon? - | accessibilityModifier? varModifier? ReadOnly? variableDeclarationList SemiColon? - | Declare varModifier? variableDeclarationList SemiColon? - ; - -variableDeclarationList - : variableDeclaration (',' variableDeclaration)* - ; - -variableDeclaration - : (identifierOrKeyWord | arrayLiteral | objectLiteral) typeAnnotation? singleExpression? ( - '=' typeParameters? singleExpression - )? // ECMAScript 6: Array & Object Matching - ; - -emptyStatement_ - : SemiColon - ; - -expressionStatement - : {this.notOpenBraceAndNotFunctionAndNotInterface()}? expressionSequence SemiColon? - ; - -ifStatement - : If '(' expressionSequence ')' statement (Else statement)? - ; - -iterationStatement - : Do statement While '(' expressionSequence ')' eos # DoStatement - | While '(' expressionSequence ')' statement # WhileStatement - | For '(' expressionSequence? SemiColon expressionSequence? SemiColon expressionSequence? ')' statement # ForStatement - | For '(' varModifier variableDeclarationList SemiColon expressionSequence? SemiColon expressionSequence? ')' statement # ForVarStatement - | For '(' singleExpression In expressionSequence ')' statement # ForInStatement - | For '(' varModifier variableDeclaration In expressionSequence ')' statement # ForVarInStatement - | For Await? '(' singleExpression identifier {this.p("of")}? expressionSequence (As type_)? ')' statement # ForOfStatement - | For Await? '(' varModifier variableDeclaration identifier {this.p("of")}? expressionSequence (As type_)? ')' statement # ForVarOfStatement - ; - -varModifier - : Var - | Let - | Const - ; - -continueStatement - : Continue ({this.notLineTerminator()}? identifier)? eos - ; - -breakStatement - : Break ({this.notLineTerminator()}? identifier)? eos - ; - -returnStatement - : Return ({this.notLineTerminator()}? expressionSequence)? eos - ; - -yieldStatement - : (Yield | YieldStar) ({this.notLineTerminator()}? expressionSequence)? eos - ; - -withStatement - : With '(' expressionSequence ')' statement - ; - -switchStatement - : Switch '(' expressionSequence ')' caseBlock - ; - -caseBlock - : '{' caseClauses? (defaultClause caseClauses?)? '}' - ; - -caseClauses - : caseClause+ - ; - -caseClause - : Case expressionSequence ':' statementList? - ; - -defaultClause - : Default ':' statementList? - ; - -labelledStatement - : identifier ':' statement - ; - -throwStatement - : Throw {this.notLineTerminator()}? expressionSequence eos - ; - -tryStatement - : Try block (catchProduction finallyProduction? | finallyProduction) - ; - -catchProduction - : Catch ('(' identifier typeAnnotation? ')')? block - ; - -finallyProduction - : Finally block - ; - -debuggerStatement - : Debugger eos - ; - -functionDeclaration - : Async? Function_ '*'? identifier callSignature (('{' functionBody '}') | SemiColon) - ; - -//Ovveride ECMA -classDeclaration - : decoratorList? (Export Default?)? Abstract? Class identifier typeParameters? classHeritage classTail - ; - -classHeritage - : classExtendsClause? implementsClause? - ; - -classTail - : '{' classElement* '}' - ; - -classExtendsClause - : Extends typeReference - ; - -implementsClause - : Implements classOrInterfaceTypeList - ; - -// Classes modified -classElement - : constructorDeclaration - | decoratorList? propertyMemberDeclaration - | indexMemberDeclaration - | statement - ; - -propertyMemberDeclaration - : propertyMemberBase propertyName '?'? typeAnnotation? initializer? SemiColon # PropertyDeclarationExpression - | propertyMemberBase propertyName callSignature (('{' functionBody '}') | SemiColon) # MethodDeclarationExpression - | propertyMemberBase (getAccessor | setAccessor) # GetterSetterDeclarationExpression - | abstractDeclaration # AbstractMemberDeclaration - ; - -propertyMemberBase - : accessibilityModifier? Async? Static? ReadOnly? - ; - -indexMemberDeclaration - : indexSignature SemiColon - ; - -generatorMethod - : (Async {this.notLineTerminator()}?)? '*'? propertyName '(' formalParameterList? ')' '{' functionBody '}' - ; - -generatorFunctionDeclaration - : Async? Function_ '*' identifier? '(' formalParameterList? ')' '{' functionBody '}' - ; - -generatorBlock - : '{' generatorDefinition (',' generatorDefinition)* ','? '}' - ; - -generatorDefinition - : '*' iteratorDefinition - ; - -iteratorBlock - : '{' iteratorDefinition (',' iteratorDefinition)* ','? '}' - ; - -iteratorDefinition - : '[' singleExpression ']' '(' formalParameterList? ')' '{' functionBody '}' - ; - -classElementName - : propertyName - | privateIdentifier - ; - -privateIdentifier - : '#' identifierName - ; - -formalParameterList - : formalParameterArg (',' formalParameterArg)* (',' lastFormalParameterArg)? ','? - | lastFormalParameterArg - | arrayLiteral // ECMAScript 6: Parameter Context Matching - | objectLiteral (':' formalParameterList)? // ECMAScript 6: Parameter Context Matching - ; - -formalParameterArg - : decorator? accessibilityModifier? assignable '?'? typeAnnotation? ( - '=' singleExpression - )? // ECMAScript 6: Initialization - ; - -lastFormalParameterArg // ECMAScript 6: Rest Parameter - : Ellipsis identifier typeAnnotation? - ; - -functionBody - : sourceElements? - ; - -sourceElements - : sourceElement+ - ; - -arrayLiteral - : ('[' elementList ']') - ; - -// JavaScript supports arrasys like [,,1,2,,]. -elementList - : ','* arrayElement? (','+ arrayElement) * ','* // Yes, everything is optional - ; - -arrayElement // ECMAScript 6: Spread Operator - : Ellipsis? (singleExpression | identifier) ','? - ; - -objectLiteral - : '{' (propertyAssignment (',' propertyAssignment)* ','?)? '}' - ; - -// MODIFIED -propertyAssignment - : propertyName (':' | '=') singleExpression # PropertyExpressionAssignment - | '[' singleExpression ']' ':' singleExpression # ComputedPropertyExpressionAssignment - | getAccessor # PropertyGetter - | setAccessor # PropertySetter - | generatorMethod # MethodProperty - | identifierOrKeyWord # PropertyShorthand - | Ellipsis? singleExpression # SpreadOperator - | restParameter # RestParameterInObject - ; - -getAccessor - : getter '(' ')' typeAnnotation? '{' functionBody '}' - ; - -setAccessor - : setter '(' formalParameterList? ')' '{' functionBody '}' - ; - -propertyName - : identifierName - | StringLiteral - | numericLiteral - | '[' singleExpression ']' - ; - -arguments - : '(' (argumentList ','?)? ')' - ; - -argumentList - : argument (',' argument)* - ; - -argument // ECMAScript 6: Spread Operator - : Ellipsis? (singleExpression | identifier) - ; - -expressionSequence - : singleExpression (',' singleExpression)* - ; - -singleExpression - : anonymousFunction # FunctionExpression - | Class identifier? typeParameters? classHeritage classTail # ClassExpression - | singleExpression '?.'? '[' expressionSequence ']' # MemberIndexExpression - | singleExpression '?.' singleExpression # OptionalChainExpression - | singleExpression '!'? '.' '#'? identifierName typeGeneric? # MemberDotExpression - | singleExpression '?'? '.' '#'? identifierName typeGeneric? # MemberDotExpression - // Split to try `new Date()` first, then `new Date`. - | New singleExpression typeArguments? arguments # NewExpression - | New singleExpression typeArguments? # NewExpression - | singleExpression arguments # ArgumentsExpression - | singleExpression {this.notLineTerminator()}? '++' # PostIncrementExpression - | singleExpression {this.notLineTerminator()}? '--' # PostDecreaseExpression - | Delete singleExpression # DeleteExpression - | Void singleExpression # VoidExpression - | Typeof singleExpression # TypeofExpression - | '++' singleExpression # PreIncrementExpression - | '--' singleExpression # PreDecreaseExpression - | '+' singleExpression # UnaryPlusExpression - | '-' singleExpression # UnaryMinusExpression - | '~' singleExpression # BitNotExpression - | '!' singleExpression # NotExpression - | Await singleExpression # AwaitExpression - | singleExpression '**' singleExpression # PowerExpression - | singleExpression ('*' | '/' | '%') singleExpression # MultiplicativeExpression - | singleExpression ('+' | '-') singleExpression # AdditiveExpression - | singleExpression '??' singleExpression # CoalesceExpression - | singleExpression ('<<' | '>' '>' | '>' '>' '>') singleExpression # BitShiftExpression - | singleExpression ('<' | '>' | '<=' | '>=') singleExpression # RelationalExpression - | singleExpression Instanceof singleExpression # InstanceofExpression - | singleExpression In singleExpression # InExpression - | singleExpression ('==' | '!=' | '===' | '!==') singleExpression # EqualityExpression - | singleExpression '&' singleExpression # BitAndExpression - | singleExpression '^' singleExpression # BitXOrExpression - | singleExpression '|' singleExpression # BitOrExpression - | singleExpression '&&' singleExpression # LogicalAndExpression - | singleExpression '||' singleExpression # LogicalOrExpression - | singleExpression '?' singleExpression ':' singleExpression # TernaryExpression - | singleExpression '=' singleExpression # AssignmentExpression - | singleExpression assignmentOperator singleExpression # AssignmentOperatorExpression - | singleExpression templateStringLiteral # TemplateStringExpression // ECMAScript 6 - | iteratorBlock # IteratorsExpression // ECMAScript 6 - | generatorBlock # GeneratorsExpression // ECMAScript 6 - | generatorFunctionDeclaration # GeneratorsFunctionExpression // ECMAScript 6 - | yieldStatement # YieldExpression // ECMAScript 6 - | This # ThisExpression - | identifierName singleExpression? # IdentifierExpression - | Super # SuperExpression - | literal # LiteralExpression - | arrayLiteral # ArrayLiteralExpression - | objectLiteral # ObjectLiteralExpression - | '(' expressionSequence ')' # ParenthesizedExpression - | typeArguments expressionSequence? # GenericTypes - | singleExpression As asExpression # CastAsExpression -// TypeScript v2.0 - | singleExpression '!' # NonNullAssertionExpression - ; - -asExpression - : predefinedType ('[' ']')? - | singleExpression - ; - -assignable - : identifier - | keyword - | arrayLiteral - | objectLiteral - ; - -anonymousFunction - : functionDeclaration - | Async? Function_ '*'? '(' formalParameterList? ')' typeAnnotation? '{' functionBody '}' - | arrowFunctionDeclaration - ; - -arrowFunctionDeclaration - : Async? arrowFunctionParameters typeAnnotation? '=>' arrowFunctionBody - ; - -arrowFunctionParameters - : propertyName - | '(' formalParameterList? ')' - ; - -arrowFunctionBody - : singleExpression - | '{' functionBody '}' - ; - -assignmentOperator - : '*=' - | '/=' - | '%=' - | '+=' - | '-=' - | '<<=' - | '>>=' - | '>>>=' - | '&=' - | '^=' - | '|=' - | '**=' - | '??=' - ; - -literal - : NullLiteral - | BooleanLiteral - | StringLiteral - | templateStringLiteral - | RegularExpressionLiteral - | numericLiteral - | bigintLiteral - ; - -templateStringLiteral - : BackTick templateStringAtom* BackTick - ; - -templateStringAtom - : TemplateStringAtom - | TemplateStringStartExpression singleExpression TemplateCloseBrace - | TemplateStringEscapeAtom - ; - -numericLiteral - : DecimalLiteral - | HexIntegerLiteral - | OctalIntegerLiteral - | OctalIntegerLiteral2 - | BinaryIntegerLiteral - ; - -bigintLiteral - : BigDecimalIntegerLiteral - | BigHexIntegerLiteral - | BigOctalIntegerLiteral - | BigBinaryIntegerLiteral - ; - -getter - : {this.n("get")}? identifier classElementName - ; - -setter - : {this.n("set")}? identifier classElementName - ; - -identifierName - : identifier - | reservedWord - ; - -identifier - : Identifier - | Async - | As - | From - | Yield - | Of - | Any - | Any - | Number - | Boolean - | String - | Unique - | Symbol - | Never - | Undefined - | Object - | KeyOf - | TypeAlias - | Constructor - | Namespace - | Abstract - ; - -identifierOrKeyWord - : identifier - | TypeAlias - | Require - ; - -reservedWord - : keyword - | NullLiteral - | BooleanLiteral - ; - -keyword - : Break - | Do - | Instanceof - | Typeof - | Case - | Else - | New - | Var - | Catch - | Finally - | Return - | Void - | Continue - | For - | Switch - | While - | Debugger - | Function_ - | This - | With - | Default - | If - | Throw - | Delete - | In - | Try - | Class - | Enum - | Extends - | Super - | Const - | Export - | Import - | Implements - | Let - | Private - | Public - | Interface - | Package - | Protected - | Static - | Yield - | Async - | Await - | ReadOnly - | From - | As - | Require - | TypeAlias - | String - | Boolean - | Number - | Module - ; - -eos - : SemiColon - | EOF - | {this.lineTerminatorAhead()}? - | {this.closeBrace()}? - ; \ No newline at end of file diff --git a/src/main/frontend/.gitignore b/src/main/frontend/.gitignore deleted file mode 100644 index 4609e81f..00000000 --- a/src/main/frontend/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -dist/ -*.local -.vite/ diff --git a/src/main/frontend/index.html b/src/main/frontend/index.html deleted file mode 100644 index 25d22f85..00000000 --- a/src/main/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Code IQ - - -
- - - diff --git a/src/main/frontend/package-lock.json b/src/main/frontend/package-lock.json deleted file mode 100644 index 287e6a3a..00000000 --- a/src/main/frontend/package-lock.json +++ /dev/null @@ -1,2077 +0,0 @@ -{ - "name": "codeiq-ui", - "version": "0.2.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "codeiq-ui", - "version": "0.2.0", - "dependencies": { - "@ossrandom/design-system": "^0.3.0", - "d3-hierarchy": "^3.1.2", - "react": "^19.2.5", - "react-dom": "^19.2.5", - "react-router-dom": "^7.1.5" - }, - "devDependencies": { - "@axe-core/playwright": "^4.10.1", - "@playwright/test": "^1.51.1", - "@types/node": "^25.6.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^4.3.4", - "typescript": "~6.0.3", - "vite": "^6.4.2" - } - }, - "node_modules/@axe-core/playwright": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.11.3.tgz", - "integrity": "sha512-h/kfksv4F0cVIDlKpT4700OehdRgpvuVskuQ2nb7/JmtWUXpe9ftHAPtwyXGvVSsa6SJ64A9ER7Zrzc/sIvC4w==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "axe-core": "~4.11.4" - }, - "peerDependencies": { - "playwright-core": ">= 1.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@ossrandom/design-system": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@ossrandom/design-system/-/design-system-0.3.0.tgz", - "integrity": "sha512-flW4PBob1WCjyero4HA8/gYHbQe+ufy2XpQ5EpjO988LdNaM/oArj4gONQSdXdGGlQ4zoXzuRTgPjDDBB61o2A==", - "license": "MIT", - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "@deck.gl/core": "^9.0.0", - "@deck.gl/layers": "^9.0.0", - "cytoscape": "^3.30.0", - "cytoscape-cose-bilkent": "^4.1.0", - "d3-force": "^3.0.0", - "d3-hierarchy": "^3.0.0", - "react": ">=18", - "react-dom": ">=18", - "uplot": "^1.6.0" - }, - "peerDependenciesMeta": { - "@deck.gl/core": { - "optional": true - }, - "@deck.gl/layers": { - "optional": true - }, - "cytoscape": { - "optional": true - }, - "cytoscape-cose-bilkent": { - "optional": true - }, - "d3-force": { - "optional": true - }, - "d3-hierarchy": { - "optional": true - }, - "uplot": { - "optional": true - } - } - }, - "node_modules/@playwright/test": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", - "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright": "1.59.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", - "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", - "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", - "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", - "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", - "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", - "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", - "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", - "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", - "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", - "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", - "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", - "cpu": [ - "loong64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", - "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", - "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", - "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", - "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", - "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", - "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", - "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", - "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", - "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", - "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", - "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", - "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", - "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.19.0" - } - }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/axe-core": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz", - "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.27", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.27.tgz", - "integrity": "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001791", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz", - "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.349", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.349.tgz", - "integrity": "sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==", - "dev": true, - "license": "ISC" - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", - "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/playwright": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", - "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.59.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", - "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/postcss": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz", - "integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/react": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz", - "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", - "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.5" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.14.2.tgz", - "integrity": "sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-router-dom": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.14.2.tgz", - "integrity": "sha512-YZcM5ES8jJSM+KrJ9BdvHHqlnGTg5tH3sC5ChFRj4inosKctdyzBDhOyyHdGk597q2OT6NTrCA1OvB/YDwfekQ==", - "license": "MIT", - "dependencies": { - "react-router": "7.14.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/rollup": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", - "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.2", - "@rollup/rollup-android-arm64": "4.60.2", - "@rollup/rollup-darwin-arm64": "4.60.2", - "@rollup/rollup-darwin-x64": "4.60.2", - "@rollup/rollup-freebsd-arm64": "4.60.2", - "@rollup/rollup-freebsd-x64": "4.60.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", - "@rollup/rollup-linux-arm-musleabihf": "4.60.2", - "@rollup/rollup-linux-arm64-gnu": "4.60.2", - "@rollup/rollup-linux-arm64-musl": "4.60.2", - "@rollup/rollup-linux-loong64-gnu": "4.60.2", - "@rollup/rollup-linux-loong64-musl": "4.60.2", - "@rollup/rollup-linux-ppc64-gnu": "4.60.2", - "@rollup/rollup-linux-ppc64-musl": "4.60.2", - "@rollup/rollup-linux-riscv64-gnu": "4.60.2", - "@rollup/rollup-linux-riscv64-musl": "4.60.2", - "@rollup/rollup-linux-s390x-gnu": "4.60.2", - "@rollup/rollup-linux-x64-gnu": "4.60.2", - "@rollup/rollup-linux-x64-musl": "4.60.2", - "@rollup/rollup-openbsd-x64": "4.60.2", - "@rollup/rollup-openharmony-arm64": "4.60.2", - "@rollup/rollup-win32-arm64-msvc": "4.60.2", - "@rollup/rollup-win32-ia32-msvc": "4.60.2", - "@rollup/rollup-win32-x64-gnu": "4.60.2", - "@rollup/rollup-win32-x64-msvc": "4.60.2", - "fsevents": "~2.3.2" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/typescript": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", - "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", - "dev": true, - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/vite": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", - "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - } - } -} diff --git a/src/main/frontend/package.json b/src/main/frontend/package.json deleted file mode 100644 index f16a702e..00000000 --- a/src/main/frontend/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "codeiq-ui", - "private": true, - "version": "0.2.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "preview": "vite preview", - "test:e2e": "playwright test", - "test:e2e:headed": "playwright test --headed", - "test:e2e:report": "playwright show-report" - }, - "dependencies": { - "@ossrandom/design-system": "^0.3.0", - "d3-hierarchy": "^3.1.2", - "react": "^19.2.5", - "react-dom": "^19.2.5", - "react-router-dom": "^7.1.5" - }, - "overrides": { - "dompurify": "^3.3.3", - "lodash": ">=4.17.24" - }, - "devDependencies": { - "@axe-core/playwright": "^4.10.1", - "@playwright/test": "^1.51.1", - "@types/node": "^25.6.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^4.3.4", - "typescript": "~6.0.3", - "vite": "^6.4.2" - } -} diff --git a/src/main/frontend/playwright-report/data/52d6e968bcc3e3f9fb8eaecdf7ea2f3d2ab41deb.png b/src/main/frontend/playwright-report/data/52d6e968bcc3e3f9fb8eaecdf7ea2f3d2ab41deb.png deleted file mode 100644 index dba53727248618b9657b7dbee70c115599d531a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72307 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

k(#H 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 UF5=6n-H%yJNa|gofTq{~18aajod5s; diff --git a/src/main/frontend/playwright-report/data/813e22f62153becae158a32a0ef8aa8037da1508.webm b/src/main/frontend/playwright-report/data/813e22f62153becae158a32a0ef8aa8037da1508.webm deleted file mode 100644 index 65ff4263913ad2700dd90e595300644ab9be6a27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158252 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�yng-RDAq;7Xrxv8;bn>yh4(&pgLUPRk;yb93b zws?S0BgXw}aom#IDw5U3j(|ua@WL&;{7KBFz>0$ngscArYspoCYe=gGL)2Or++h|R z?oScoDrs9Aa#0$~S?#c)Fb(Rsc+h-bZAE*iK6>&jbW7hm>k}3aB>@dPFBfk2lT49Z z%0eUs14z9et;wV81*t4+KdL zE?}lfLZHG-ks`w=o3{d0n6Nqx&2{x2L7?0g9aM-K@2Z{wMg#jbwLUCFLp)+lPeD8T z29h9B(f1Ra#w!%|LD*E@?cS_CoTW+me*S&d+{g}v1K*Je<|+OF+V6t=mOAS) zT6l~YYvyU(oNnI>ZcU$Zx@HO#`qP6eIKKT#jU*jQW`-%Mz8#-_oUWcAgJ(|WE1USP zULcMC15!vk^~M%rC3qRIIGBn_&lTm|l4jZgF%paKf|t#rFPuGS^&i`y#bwZw4Bh4y zNOd!07N|i@O9M~663W2x%H+4 z{B@3lDJyyKC8~;dgyBT6zVeaT3*d7N$}gDJ;bR)HP<|=B_11}P;}O%uWBJb%$Yl^N z_9R(0vF_|dl12W{`5n>{L*B>QNsXx&H_m|PG9M2;`5dJ3x%zpHWjO$Zflhz_C_FtgyXpvqmXNiKo+ zErfmtspW>pNkD1=uOg7GKW?~-W-L3e>)-gp#k5MXz?7aKR^}NeNrE@SLY>sqyYmfY-Qi(|WgN^{ibN^R#V6hvF{bLf0*LKuN`ubhz&3&By z`&$Oy%YBXQtowBL7RAThNM=Jlt7OC?nz5KQmzwHLK8bWy)N#`sfZNq?fvw zrL+>l259#+#_3OiNx#*8AB@?`(m=mPGO{d2X^mffh3NARg(ZnlKytWEZfKFU$Vr2} zByLF6G=wI5n2}S`IDy?{JwCM~u^zJfg^DA$MC2o}s&Rggd8I^<@N<5McvT8YQ?)q% zgOJ;@WVInD5X5~lD8GkYxbDoYraOm`@QZivQ`+=Bv-b?#<^7DEy>26b&6FAwdyDt9 zO+%3IiS-`Z!=E*ja*GxbBz)t2#uUK)3ih5$>lQ)6FQ~mE{u|Ie4eg2jPYsW)+&K7l z@eiTUZL=Y4CNv%-^c0U%`2TU<&r@1z;=!LADa?OvBnk!pFcN`Fv+y4|5(PhAo#Wy2 z)2#;+r)Hf826;rNfvYl;$1<7SFq`6+NAkNdmDn}=a{T~6$8`cE(|5y!v}}&Z@0TYqgfk1wa3E@LMF7PkLE&+R1zc^w`}bL-M+Xh`c*)<#3o12)esx z!k8uwAbU$!AV0d-2X3TyGWw#P&r^&CE(KmwJzN*V|$`;5;Ji7`DjRYdnHUaNm zFv7hJA}Es@)#aM*?+2ul01!B_d|MuZyKpt~F7_6?qzRiW?loeO4LGs`I+MMrWe-jV z6gm`Uz>N_d;m{w~s3b5&n6NQrlg!84Rc8NDl}!~;ao`p`NiEbQZae_p{V<2}xMd(J zl<+_Ah}~-8A=`Vr`Bp^d)DaG0R3l8qUw>94L;GFW44D-Ze%R9HiA`*Tqy(y!OWc6(p7wf}lag6hv8LgkJCKBVo!}~%W zKfG3TGJDStweqw!UrdPRiuUNfH>OKUZ3va2II29yaaN7`k26fhZFfQ(jbAzQZ+mG8 zXac!Fe$bZo;%j|{q~eYqO`1JpHt=_~opQ2;U9&}eNpgL_p4*-ehlcOT#ai=kzH+CZ z{3Q?nxP9dgo9^m0L>i)R68ayyRUrf2(Jwd*2H>#a4=0b36P!8j6W>+1;@^m859X$c z;J?ypiK;2vHsqda$fPaxR%_2d+MYPE6@eYETMisAuDdi>K;ZeSt zGUW^&sXU{f#)RpMmBE)8sg>I4jdT{F$acT@$fd$U!ZkhVM&nfYd8umuax|S{Wrl4C zFa8V1H(PEINO|zBTq1P}#d8R`&?0bCvav;~pE4ez6|X=*XS|2DJl4k)Z!0QkSVR&w zxAv+|rbs(dv(wBEsHXUXku&aQGjdf;`mAZ`QG+~)(%R?%w+@_>Hr>_AdNIBGhtz@z{7lp@d%7pbP@MH>JUlq$>1Ka$klsMjY;GG3%x$LW)a_)PP?N=&g+zd2k~*IYpQPm`D*6-74>`Z14ns0+tAc zI>ZR?29Qy53$T-v7{-GIy`omLAFy7;$;xQsRf%NsCgO-wQn8CcovjZDCZw?csk6>a z^xx~@f0oAUzmX@tkF2L0Gz@#dyj}T6uL#J#Iy2QsvzxB&>*o2(0X{}>qAT(G;#rm5 zl8`!kz0pcdzFN@Ic3MI&!o?zghNFSFuZ=EhD(HA<9an!Q3IDr&U+biC5^y!RW(QJ%83*cuwqlG14spf(Jn1oy0-6i2Kve!7T7+o(ByK@tNOY z^fx@vlck+WO5myAmo!#R>k-VtRy&%jVHn`U{|~Z}sri0)39<$RKWVKbm%wB!7sn0K z&^tO?zDO~TJ$mKp!qGN?BFIyLi^AE3MjpcgZL4?q8(-THO*9Rs1BdbTWB%>!RI=+- z$!5i2>a~Czm4aM=jGTk2)B*c^wG%qm(S;y!Ln~9kz~lJkF6jgc z63+L~pFB(p`o~z~y#)`HL79P}a=b^h zPShfoQC=9TUO+=v#x6p!1 z!45c7GcT123om>sFyKX1ny8*GjCP%@-{NYn&_#9xpa zUVXN{(vF2#O7}<=wf)WC;T=S|j&`a_ThW=F%dROXGH`qiu+=xqMSC-nV!Tk&=S;bkgKHJ>dseNA|gKKgWt{Rxi9V2a0~YC_Q%Y0 zTjOoy#P|9VWvNPya~EMys3=lo)04@%rR<>P7oto>!l25A-F6@~Wl5E{N?_Tp6QMc_ z`_<@U$B!s%<-5{+LnaDd=rJonDfm%zXegRe1#aD#OsseW$G?9O32m)>uwt!8N?&>z z0dy25=v~+eQ+R{5Y7G1)PN*gvf-=ak!Es#>q-a$k%)Isp+5u&Be>yd7(y;=!Hh$|h zQy9gba>`x!__+G!P-iAUgpzr$uc0;|$zr;R$clU~ZjmachiC`UpO8c=9l1vR!mA=} zNKF=`x_`V|!TBC^@SFG5V)PLtcl^jJX;*#plLsbwk`VBlig~%f=a%0oalUTnWm-v42OLMIb2A*Hh1Xv0BFr2gkO7** z4F?=RSd?S~xxD=)1zc%%~vb@^XVD~BniT}{oWOfSOHScJ+t8*HDg(X978vVarQi|W(!idk6bR+|UlHqo~dA3(~Y z{Rgo|QoiI<_4Vu=4G~2BF^XO%s(BL)NHl3klFFAe%3p(ql>kdl_M%j6=wQcyGdGGmri)L&tl&J-oK!zc!>hK_hjDmx8`Yp|8Qu|3UKsjFLFGzOso4L__i8D)9)r1=VQBuJtR-Tk^ zxiQiURIQQpkl4XdNq&PHaOG4+95zoH3HU?-UNN_7>HP6N&{6m5>kHS>Q^!d;TN%);il32Z7qz1;=_i9loP)=H zUu6%NWjYvL&qLZsmDBZ~ubW<~llL3pQ=5YKd32-}fKFb`o%K%&PBJf1uEbk{!}84n&=Flc4s4(PJA3j5Vmv#$d3^nnUUL?X(ls z0cl~SUOcWs-|Qn};~Ed4ObX}i99o%1TZYRM@dR%ZF3v7f9b*gQtYOzOn?uM zX_xZO3PXD#l?$3QWZ+e12j~Aq8J`kmN3Cs4I2n`k`7}qN8OH<$Eu2DL@KL9B#+a>$ zy`$RR90b@!|G{}jDXu!>cVE1O9}#I_z;Pg?iGcIB^_vrMI{la%B8I2{YLFdKA=n7t z&RiYnbn)YLu9k(N*U%jwicMjRe4Nns9ZQyAi$+O}5y?fWYm|TC+N!+$A~H%2l?F4q z=mfdTB>&|+nQ{>)h!`63IRO6m`xj&_K!+H$lES3~K%WD}p)l(5yA_eDUjVx+V9;2? zVXFjUKAi~jDtfO$A9tSCKuoM%#`D+UtF=) z-7=%g^DXsX@GNjRGSDx|`FU(YPe#QMaA@F7*zyCqmi@~-^9X^@pLZX)7G(d4->CcR zFNPht24B42r1Lq`i18swC7M0Atl%k1E44v|25;t7wNRJP=0jJ0F+598&Ea=+%Dbn! zYr*B%iUDuEgru`spV1zjL^pySyW#2<*&;_6y3gX&ON;{2FDv_HxEFo1m-dMX!(Dei z(qgng=cgCc@xvz3a%p;N;mks`_K2NG$e1K`;=jZ@BCG`IzS5LDLp6gvZbp1@Gz=!aveMdWo~}2PuFI4G$qo$iPxp`SB-~C1 zkSQO(`8xQn<9kD~NaRv9R%*NJz3bd+R4f|aBF@G50dh+rVIFeHm&HT16w&(vCec{E zF-*7a9p6342~Q=CaSR`;pe|3$^`Z5H{zN6&7Y1e_VeA;pX-&8dhvT~+J|6!es;;k} z4syRQJLyFk9EPk#LW+A$xYa@XJ)e9EiYiTeiQmO5dc6$z^4_&VF*d09Ujo z9SitU?aA|wmkUxioidiZ=~o>jH~f{!lw^wMavpYC*h!# zh0P;J5lWXLzmTFxFs%J(-CwvOVmO-+eeXfFKuIA`V>Z&Q>aP)A9@W5C7L_fnT4otq zO=FL*Ow>SW;P^Y;Ujre;71lR zG@S(JRMED}DeQW3-?8XZ_0?|HGRZ6Ou@qUI-DXuNNltxFDf*e5}f1ZZD3OR^X&^4o5s9;na4X!cs$gI!#<~9^;4yad7kSt&%IhN`% z`sCE&$Xv^NeYo6vMyp+FPa&j()T45QlUO4oI^#1fL*{+>TbnUS7Khw$*lM~}&3!>h zR|0r4hwpRRTOnPcbny(j4RHtvyUq~-x2FiCY??`9#bmp+w2`|@kkTTPb;CO$R6`=v z!^BaA47AyNw3cV6;j#v~$C>7?$cRpno4crLdMktVKGx;a518@^-h%0RX*R2$;+G6? zD7?PMD+dr2rM*baBKjE`m`RYDx=t2w?mOw>j+M%+ph9X7z3A!eLRLk&t$SK?(rq3{1$?el&yDsRj?!)9Tk{yTuam8L+eVC z?Qm&jKB&D{y$eYg)Da|kdPgQ3{I38Wsf_iM!-e6Im{IRmC#7Rr`iH^6(A+}i?Z zdq}dx3%EqfC@PDUjKl$6&nZS3V^f+;#@lOXGwJNImQ&61yAnki`VA#RKp%q`0nNw) zgKyfw_xS8MNw!yP<~A%Yn-77N&K4-nkz4LZ}dF`p~)&@2{6v&!4fI zt!%74eGhKV`>^87>JmkM(E{l)yu#guc;#~bvu1Oq&g!J{iw>9ZXp(Es<3%EjrSa8L zQi*K*{8zp?i9F)Qs|Z4!GV;kL$Aa*JlJ4+ipjV9S7U9k!2(h%;I5;OEi7j~|UmW)2 z+T-eT;qc`#PW$+2>f$RRDdR0!hFSIe?vqG<)$7cJ9E=S-tnt31OP`y^)GMx}rt@t3 zuQ#&}JQ|(h3tj|%=nX(GctK={@>mAXp?A1P zh2@-4zx(0h5ru{>q##9q!+a>nL|O~mFRbt0$a*Bz9J5oTEwSvwJu?$ZPyrAN(Yc&R z=EDxP4zP>B1?u~D@7uu3j*xkmEVdLHtSlQ7R~sA(p1Z9|Sn12&6S99>&|l@|)>^fU z=b%aYim^E|*)~npyzm}6vx7_weDrcc(<(Q4Wuh9Ubgpb#b|&e{21W16N6l`ut-02< zga{U|x&m6?OZ}A@Jv!h12u(Aq7IoX&+5C2hVHoxy9aYL(N9@xW!|qr!xY&L%9#yuE zLLDQ_YaH_gNk!9}Dtw~ZW_!L7XIz4LfMOJOS(2f~8CO}-M4+MuuaRG%a+`=EQ@Pwq zXPRDiMO*?$NTPg=kKChOmK-~;eC=~go+g+>=+EkXhyF@R%2MouqCG&c^`e-w|IKS5 zqTx5%*@Ny|H#?Xro)0|3oAz=&(I5!@4qY*4ZEec&EaB<5DL~xQ=uQ#zr~it1w2?r3 z3-MTCuC8v#%$$;i2hns&8XWvQkc=^^$@am{XZWwph`vk-*F3cF>_cBM^`spFefPEM z?r-U4VQMeEGfsvAM|$}ZAL`4Rvf)J{Hx%KQCUoChlgUa`yn>Z1Q}cS5#qz%vhYtj5 zq&~vsVj3~5F?sw(L34>5Qm@9z+~&FP?y5)p_IQSo>Z>PF zJV2QLn)}E{2|w%qd7l1SU+S+F?deYZjf@uyX0K~$T-j+3r_AgtbmNmkIcWh;C*Rv^G1gY*(;phP`PN*2Xy4~ON8$*Ss#Ivo$%{d^!^Xfwj^`L#)f=1 zsA{acqH?8C-`+JhmM!`VW9k)~X6WwmNlpox3IGC%?&F@U88op3J5kgJB)|${&{_Gs zS61MGheK=7fw9hrQI?4QI}dE@s`E&*2XwCR)66T9LwD>!Bs0Y58RzoJ<7*J}_YCnB z6=sKT4lHf{U9PwC$ezDOD*S)o28^J&(grdJ^irNQFh!r$BkfXqk|vg;;zFQa4Fg_0 z-bEt(q*VQWf`d%{U>E?5eE+qZzvW%bo9!rCGjF;#T_>+U8R{r&tZuP+Z zT4LgE{jFRWgIvn;oTm)6JEtinX*nH?2BJJYl01bx)DlF;VUWmzLcrETTIs&D$;*~i zW+PZN>HlC;Z*R?2`*G>sTG*JJ@Q=@emh>Mul4auy^yM1#9_hyO5~>yF3v0j&c_ODq zp1Inmbh2)|HbUQHMqM6rm&O2I!uY`53qU~plT>*T+$BHKJM467TXz(+lR?o87wKbR zyAP{`bue^}$zndzP;{0Mw^>H}n;G(X)CFO1wO8wM0Nhuj|A<=!JCRjQD#w3YZlrSa zGZn2+DJIA*aSzv~Dqd0s04ACiBFo189w9IV3QFVLw9q1We+`UjV_3q^3OLB=d>v3{1HO10(EQsfLejX-Apfst!z7gHB$1 zOkl~5pQa7SfW5#OGgrLq0|49YTszssBQzPFTz7sQYvKCwSYK;{aKZP+NsefpY-Mgy zG=_q#uV4@M=16I=@_75@!R^B`o=XF8t3l0P+*QGJi54w8`^`V6>0@Rpyvjlhk%Y`Y zD%JfGIoXYv48~4$!YA`U7UGX*=S#)8BS4qq(Q(nObUh3i{1YKQ^*Qt`M%|$7ini>+ zj)|>z|KvaYxweRAgaeJlI5+&LZ8Y5`Sk^OGI#A+D2T@Vw*rT{k-jYfUs|!eUjb9E* zaMg0ryNi{^N?aAhXLmPGIu2v@`5B;F(q(@6(yWSO@SA`1y`jWrpM8`#oJ&j>6&mwh zb@Dv#G^;$KeB`Fwt@A!Ua-f;GDzJ~3YeKb2j#+ZDS{NnO+bFG;tguKs+TP@0=?xN) zI0>E$7DX~R`%LFad5MPj!q1Rb$Zure1c~C0mo%7mJQ_RUgLWe+E`MAOk?jW~(7T3T z(E`WTy*ouD{Hzv*)B=YTm-Tc!e7&z(e?v=c^_iAd%QDYSP@`}=1jo__4j>q%dSS<1 zseMwqx~XEW6p6ELm_WMRTA{XQUnS%XOJ7N|-8g+YI^U2A*{lFO;hR45vskl%1gp~- zWkf47MjJ2vvsVcYGYS->ib{jOUo05#$20L{G_hDQ=C|18p9y}dge{<0&qfOE_pcjS zGG0Wl^o@jy+|5>i0x3&>FaZDumH+zCIK^7DUDJ8=(ac=lcX!y&59b>3UAa?;qK;!b z0$1>fB2v*nmS;9;BP5qTQu@gXFz9v)vY^`Sc7DfTVH;2#@Va8WT(MuQU98>aj`9q` z4td=$+Q4zM%NpXH)@{!|^ZHiWl*>8uEW7`dbK&zXyTU#;D83ryazA?Kw%1XbUzaM+ zX8yR|t*%V9cWqj#V;G2d?hv8Mw%^`ADOc3+g(J%+x2A_owSMl*{#&_wg(E|$O0{qw z^3iB$veGc1aRtOPpmc)Vpl-RA{iEfoi z4CCiz*!yH*4wCCeDQ@naCzs>VEB5`H#F3ANX?%Jdc?}wpZ-SJk8SDOU9P^t;siz8Q zV{c+fHvK&RA9LrS>855ZuKz-Jm>TGCM9AxZ#6KH`L7Nzrp8j8{B*jesvB@kH7BPQA zev^3`BfaVCmx&6`?aw4qmU2Hd8^ddxrJ440 z6P)zL_TjJelQ)0*z~;jdp#0gA8Qa{ta^Y#*3YAN+zMS2s(oLJ=>mcmVl9me^9XU$V zff<^Czcp6f7cs5ouzv>Oy5U?RY4&qZ;&JSM(XIm)o)v^WM`s*jNFs^O1E15Y`W&GG z>`=3BH~HdZtn*s(VLMI9L~XNFUN$M_8|3%k1b}WXH5}86-1+i$FV2HVNAO!!m;J(m z_PfM4jaWM4(#?1P%_>T7gnHCiDiyS^Gq#W)%netN^@p97$M6)O8e&8)*6-J+r%6@i zS6iiirpf*ylNADa#Z{oL037azwZ+mKI258CBt-3{2CGrnkmiH{xY+dq!&56x*aeT0!LO+&^z) zG6Pux40mCakC$@q5y+<%j>6~E;8pl%d!&1WOD4T2IP!U2QG2IFa4pCMmQlp3`&%(j z0;@<)u=c_pSJZ&HYw5r|N9Vo*4YSdcE3!HGkY)}*cmo09IZy;& z3K5!ePiP6_K{cFaZE|!Fy$qeZ@A$%aPoo3FMd$MVc<0|%ZUbxBh+|CaN^JwEtxKRW zM*c-T043*AYwiM8SW-A}sZM!eD2#OL{E?HGy53{2csv|2MG; z3GGA2jOo5Qj#j|aqfVm|22z$~}N1NRx)|+bBvH4xeBe(U6?NrAj8ML`8 zu9qR&t#kJ8%)|um7=-S(?Xj<;X+X1&qn7Hg;kfM~Rr{pzWklTU%;e$$&J@XOV06S~ znjI-#^gcCu%Mo`YWNFFEH`qzbXM-FLf@r$j-Kr`wL-a)A>8Hi%&@Lz)Stbr)d+jdr z(70D@4oi!AV^dQ7r&A1!6H=|G@0D@%a9sI}IZOA$AWy+(Hl5oi%>2}dG$~6K&V~UK z9lAC6G@tzIkbR56`HaR{vpx1uCp@AIB5f}qO(K@_z`u2@;1YKNzu zuj*VWJdgM@4D7Qv$s^dQ!~9Eryu&@LMQOiu!lI#i^9EZQ7QXPV>P^1pHM_{n1y{n%xxSOsKyDGT z1LC?Ggf|R(U4i-Z%gmE1CKr1y?Xk7j4k9@=Rb}n_Jb&R;EllK`)iBk7HaHA+djV>i z&7_{h%}+&L-C3gP=7aFJC+Q*VY@u&Rh_J>gUs$4cRmVNyTtR^#h?|a03xn%5aSu9| z3LKJK9d}h0fuf0O2K5aT(J0_Td*sc~#}Ux_(q~KTXP;f`QNh-c(`OgEZU9)1v2Wds zvNB6PX#7!hFY)E!K$ejHsQ5F7vIs(9q6Aq(Zp-xgN#BPHGnAR*mZTKzg!CYt6ElRf$&R#4>bH`k*xG_=Q{9J)XeWoRta zwW8~4PoI72ux%5g1kUBGslEs!G| za71iL74yA`EA5)g)ZJ_+swDf#NvYcU=zA#gIPxLmY}BbH`v@af(_%!7kl}sto>7sj zHbHE&7ug)cj+YezM(iOi+bn>7`JCe#{;=aCnGmbqLUnhxD-KP11>d6|1 zS!bi?GEWb~!Ch-Vn%W%E?(q9ToTqr-J;%+oRuB}+NEl3+$XqYjf>CYEgeCEx#(h8m zQS*0rf0ZEPf+#Z;wQ74EhhIMWq~NS+28m*C^34+Rr1ui0^tOg|8sAJc0+RWM4?o&l zv$|u^f@E>%-WND@o=fdJuH|=sZxu`sFcKLz{#Yk>Zl7Qoymes?f%P*;J8bo${(r{^%sOk_Zrf!TSN` z&S2LAigwr{Qdldu{QLyTKTg(DM;mqC=m0xZx*kP%M(ca_uh8b=hgm-GYJKyT-l&)< zUGiSbY9s4t5uM5`z$9#u_s&1KmP-1N2sn`}0@Db}lsaMk zM@HwtqYBb-so6hO;(nOT3G|Zx%US=xe_T?1vB+3lN*V^HNPd%(I*{W~KM#KaGplHz zj|o=N{P;11R)_0!&ToPgFe44Co`~a}hNfTc382^5hO3Eoo3sHMLB`C#Ne$`)$H(LX zqOO_e>A}Z_ zZq;Ed*=5dNB07ZP*H|a#VT5Kb+)51Dd_4hg)G_6}%cnm%-2@@3iL@X(Gc~(YvT?>+O}_65bg@0(BEQCh3+?V zA@wXd&8S8#pbWU4TPzcNIw(NJSqligvXEQY7HXtQYckalIzx(z4^W zNbnMH^3ughWQO*F5!!|Q6O)3A)?&|NGU1l_jWbe{96ZVWtnF=Xj}*- zT`)UJNm;uu7SV^W%iCfl(%F$msGz*ZKSkHD|1r(Bvx}YlfDWC7c(47GHmMqBWAvsH zYLE>C&w*R;9<#qmBei@4ED}5Ww{?-56i5PWd@ev{DRKcsD&tpxAO|7NDRTG07X@GqnD2OkZ$`7rG!$&P??9^?$J51{%{KRF$QUE5+wm` zN(h{eY@a>^x^qf!#=yQnVF1s1B6b$y6bZ3!t3648zo~C2!YSrqU)TNw!K1{zqYnuV zdA@C--3yWL=I@OMk{IrIuB6gSHl+$S8aAc*jX8e(t z|5*zlR!UrS2!%Z+I2H~*(@y?8vi|WOCYBR~0$0Xnt!<7UT}n$f*=GT4V15ukh=NUj zZ9NDr%KvfGKaaKk$0Wmv$0!x>AEn?_X{z;5d}I{tKb-bljgaQ+Oa;Pb2TBByroIis4dBd+nnCYfp0m9aXdu6Y6Eavi}r(A z7)z2nVaIU9B930wWkFbbd|W@3RgL&(9iSJ7xRom%2ZBfUm|PNH|0k9ya^B#6GyX}c5 zR@GkYioT^9qgJpBt;3zBks)W=MtjQX7#1)8by>pS%-<~F@0RSA@(;)j$oq!mgyeq1 z^2084!doWNWCY`RyxSkV(i|OQ!AP;GrHA0E+XZC8>24)eNmCkghvWef`p{KqR#`Tc zFa4jJLHXZ_KE>T0V+8O|$&e3@pPijotQmVW}E*kJ{v?ADr9$zb*bB%k34@ep6z)v^Le&69s;IPmC$edUmiWu&6JgOWmcz?>3{NAw_y14nDwy9jZ>q#LiQ=S=$MOh^WE zkD|;mXhvdgkS7N)Hiy)9LYWWC2M6WX&=lN#C>V`%Dto{@t&xIX*1vgXn0ZuVsFv^( z9}X#p=McI;m+Gi9GCXG6xQ|4@-;jtB+3auM7814|OouZB^xe{`1JsOCul6pfF^GD) z7^w|=>%AglyQ7kXU|sYe@28)O6}Veo}p z)y006*mQP3V#UeJ=Z~uZ?D3|3^CXG}NKRb-W2G?|s_?-+%!UmH>JW+=kVCkYx&LkD zU`8;CLN_@ym#nvY<|nd!egymAKFVwB#HfU6aK0^yf>hWF`)^x`)7Tc>#2>2KqM(ij zH&0A9KX)YAt|&@970q?QKA~8&&Yetu1f?-+>L$;E`QkRo21S0*nDdZ`0J4}eZgAlb zng)t(?=nT!`i+6~PcC7aXcK#5Tp`j+<9~66xU^+vIz&jeDu_Z5_#~?Vqy4W1@DKc_ z&n{hLg+!*hwLgNQz^lXL$Rkxj6h%P}b#l74TBm3TML`?g*1iemhfYaHMN<$k@-r}> z;J|nr`|4vWiUdcKx*7`ZRTI(p`2kn;1<(o9XKsz}WCtG!u6U}CJ?ON$z{dKt1dE-O zwv5L!RT*h{rsqCkZ9I3oK8Fy5~7~;uLk0yd-*hfORhVym&27~Ft z`d?thSvb%_@7ftpVJPmPy9_Tha4)iu`e5``85LVk0a3Mgf^eKyGK_9|ef))<ywCKLZzdcWPVI*Ie&9+nJ)DbSZg2@yrid9_Aeo3IlW5I>?h`Z)Db!E938?Bg9FAf}Vo+65TX4Pm1pK~4bC!19 zcJhIIQ@y@3i_cFoyWOB)PWP8Hy*zp8=e_2(}wH z0EF8lf>3zQUg#h@a)%N}jJ-IC*iof`PnL`?nbaXGh|YpbdF|Cu!!12+oTzKQ^mI3F z7++VRQYEM*aZL|$+NCU!UELq@$pDpvz|V=}-0*kFP<9L;LKU)67==~&wsB^`^-R+G z)KR&#A=Vwcz=hRHPuOGJ`rA7QpV~f`P$vLv(Vjf^CgHBmzm=56rmjzWIqSwM} z2}gcw75mxvZbO1wB~p~BNFpKoxbhp=9iUC?BtF0M%U~&lNAo3kVGHax8`4Tqb9o#w zQRS2T8|139X4=pi^d;7SWrx@Tc=HyL7EPX1GU$+Bh7J)e=7ZY8#WJaD4WJjUR><_ed9K^$ay=tS1Nz)21Rx z?c;%|!X*B(qZ;KT$ato>Z{khAP8wE?&A`H@DyoY=`)g2x?~aBOTk)Tqi%^o#9kM^i zo->!_dA3<@(`MhQa80xg@!ZRDA;OGXALNG%MmZZ_zg@h+)|9kl571@NzrmEp^@(K4 z6Jf1H1#SP{QQLj6wCM8`!0`sQ?OlZ_r%w`<3BKe4T9&P5dYD;z9D4+Ba_aej86n{>n}5(W4oZxCeCpiM9s>wE+H% zoG%<-f8rguKc`LOdR|hS#gQlaCKPp0?hz8Qz1$+)RoFh5{{?dx;Hx!z)c^_ zsW0Nsv4OJk`hr-IX&?36wia))GPf2BTkdK?S|EETWSN${y|&vf&f34^(uRra{M@bWk)_l5Gqyr8ouhTYaEWOjoqTJ<5kf*RQaV{#)k^<@+n40Z< z6heiQD@I0K1z?9YDBbh!!4V=M$tk{%6rdHR_#9)7_&gDg2up*Yv zS7YvyAyPoIleJ-JG{k;QV_R*imD6yoX%@4c_{;TAxQrH#69EP_+CBQJ)h(%}<3WL= z@-NlsT3Sbc*n3|viTT2hmlB(N?qf7IS=aHT1f?FIyJt z4!0t@ZzwWM6K9sL-w*+8a=4{j&(Vr=2PgWeC7I#+SU@emhS?NHhok((|MVR2N5NUm zYn$Le?V;k{cB|3E5}q%`I=X7MRt$(uV+4Gi3G4==9rP#8k;66fTV-Ag+xMPQd$STM zu8z>m-|7Y2J&GG@>@Nzb+8@ATM6l0hfnccmE4;YLhKc(>*x{c2uWxqzm@?% z+o+E~RL(*D;>CRtqOjR0$3u01&T{7D-ZSYcjc5e_N>SJpaE$Pn$^m=&DI!lgu%}5q zy!L_uLMS3U0~`&@yU!Dan@wlyiU~P%)nWJ=iF>2WBL5sXRCUb;&TF$OX6MUkj?Jbx zzoAP!!{YX0P}Dy}E04+nD9VIOH8v{w!=QLDXZA&W{W;+5ZbGJz=#vNmhPvkm!!*42 z=j7zC-DJcK7OsbsJ{ZK3mFa+M`$sB$kZS^}q^q<(10p>Q0*KUc()x@(k*+!cu(d$A zy8rO7R0Sbg| z{K0kr>i+xK^(obF0(Y~YqnESbx1A`~FYJVxeOv{Nt}*?iztVPol}zIyu3}yD#mug8 zi<@8K{-gXaaA8+)AB$ab17~C9MgGF?dVyxf=yYV!J}03f=wniQ>5TJad&23D;Yezp z14`_f#UeUGz}I!q#~;-VLGmU&nS~Udq1yPMC=x4)q+CajHW8;;CoMpE5X*K;1YwaF z0N5W{)$kBX} z>{KQH8CMOJYpC?b|4+hB;S9mS64Rc3p&wWNma(2#s%rc>eK>%NXlI3A+i^iN%d1=D z9>7_oyBa8Ac>o)D^y)tvJYiBB&Vl9s?cs}mBIql1^bIB^+v9#%!YyTn7u4>Zf? z@{Y=)l9J_tLT`4rqWvn^PcmDQhsH>pPaBl^(vT{XB`{IJ+fX(}j!1-cB^H2!R_TM- z1eh>!L86vm)RhJjGzX%Q{F*c?Ql9{nyV)`<&}k2a#*+U?WIhMzrXDyqZHea992J1l zbep$)c~^sm>Sp)s8ZTFF;tj+A>q=EeNiY_<2Q5hgKDTPesx`8R(vkbR+G`rL8jLM! z5RYU#2vvNUcNLX=$Bt2L=#^%Is|+Whw?Tk(E6tXhrOIJaiXB-aK^j{)*+Lic7$v_sj?n- zs@OUb0=Q!CX{b-~-79#r{ty=W^Dsd6F@|g&f~!-pIKdr=L)Pqpr~**2pAqT0o>+!v z0LN9yZ4#zmfl#79I0S$K=YMbE0ONIe-+D33xMWe2^!o9gy4<41ose}0Kr0#;O_43 z5=d|ha=XbpGkND3&Y9nR?)l}sb9wro+Nr9|?wwD6YgN^%we*FABZNy+Bdn}H>*NRk z!U6FE^8A&$ELmdxQwn-n8J?utEb+q>8%ye-Csy%_V2bbA!^{{P&31X_CK=bWb^#bz z;961N=zL>Yuj~C#M(t^(*!;dy0I2GWB4xr5o8Y$3vRsEqL}1UsQ=Wq;V3TndfV|~`;L=-YFq6wE|h!4tEYaT$>k+wzf@@=yVY0Ej3hWNQU z65}^_JF-W0ZcDvFI&728J=I$jJz#{KsVjYmpCtFazgdLx8bqZV5RMgK$8$?1K7h#M z;Soe%5cm6|7a^k+M|BdgyEN~u`?gDlTv#MF>+rz;{-UFaP>Y_X@vy`| z0~WItbW^xS1Nt+-eR-t`g-5u`1SZh$unT! z>ATJCJMAgI;*7Z3(XXXGr#c0lxWxxR8gE|di_0q;e~3NXoT4tfPGyb6c8v>%@K?JW zqDicKB~X4kz`Mu40R5zb5ZN0cr{19Ut!dj#-Y0x)ddqx98KkI+$CRIpg|ov&2k|$7 z36RgOXg8h``wfQsP;cjQsct%eYBnXsTu9pDfs@3%!yObc?$0?osBjx>LGApL=>@X_ zjZj-rUzK*gR6ZQgG*g7MZZHK`sgld1=^45hrZU>&D9w-?F3pXu6oPM%(QbY9d~5sL z;B70CuIBeAG_aqufcdx3I1sanS!szNZU2rxq`%hACHS8Z=yzGr$b$b29IFN(Re+*YnuNbb=oMh&_j zGoJBlO`l_RP?`KpJrOy*C!^%4G&BXg+^qZ8#|9mc>X`7N=^`Ar4T_zn#zJ?RQ97eOH*@cc??a z!aTlMt~`mB9WqsN;(pMpn3VH^PUgS_SlOxivI=jS9O}jbs=ZKlOmOd8a*J2Jy4YG9 zev{c`k~Z)J&yl+kG85dOgJHmXsts$RJfw0Y@WT0>*}VO?K9^;v;%v|2IrL=X9~Zkr z&v#_YVW{EN7vQvo{GmOfiGwoAcNgIwRx9ii4`IhIom?az6;l%m@HY3D?T_T@h1lDE zti0;1Ns<3FX4`OraQ)D#DV-8oua^D9rn~062_8e!(EJHN@LH&mY{Z2VDVG!AN-8_o zo1Eoch|}aw#?{!siH_ZAs4y6Rxv*~QuyYXW$u;Qaqt%k8%;u1m0tZR?K#^lpyLGGL zqItuJcG5}9bR z?Z5E&mUNb**zFwGdl*n|MPx>;S6UUGZygiEhN&jS@+)$=m_NK8t@t8u0IBG${y4=A zODWgCxwWF7Wx2mNS4*RAT2O?cNUU zNhP^lhmCIWm-Sh^1geXeN$0az%wqxN_-Mncf$Kq$`uY_WZtz9;BkivbK6BU4)p-ZhnPEw81T_d+_4)^xG>@xq*yk$5U^l1~ zQ=Xu_fg^VaDE{6QVUtAfVwe5)=c7)8Wv)$mqqN}?AEJY*x>`x0-+5oB8Jdu$jMgz? zSaW{}^fN|H+d&-f78`j+-@(AD{OBEM*K-00=LHzz`nmV?_`r?x6swcu0iuJ*H{~Mm z-etbR(73$VlF7Rh9>%qfEq8*)^qgfl`J*rGFZl6c^K(g+9=U&cDK&I*{Fs5Dmq&R< zk2z@Zc<~LVvhu2D&tm;?3Vlf0SuCELWh1NnA$*{?C}nvUpDywxM}nz1NM`UKhskzw ze^7XY!{!AcSw2dP0$p51s2~s}^;&>cEw9XO05&y}*?fXDN$_>mws##88NI@~X0xci zkpF)6?gxy*i^wq2F-EMWotC)cK9`8yj%oxSYay!1sRhy%f=1O3xugxxq7L9s2335F zyka^&j;y+Q3p7L9=BIHW_)Kga2+d$6NC{`7c!R5eegm}0oX^&|1U%BIu069k8@4%! zRMMfq?KZ+KVa(_Kz|G#gSR-Fe8ZlL$bh#3gLJ#s7!5C#=E&Y0QPIlN_%=u(T6Y=|m z;ccg|AET=x8HI|VI#TK8OHA4)qyMzwd3@m(5vh?_++yd;N5nF+8nIo0tJ3MjrJLIY zM;{}q^qwRve(ON;SZkFETo6cXW$DC7x@}5aMgyf_gFPVEEU|F(7`w&XgGuOM8x`t< ze_!Atul!u@Y~nogWT<2Jhq{hh80fTw)%lSP%Mj55Y9SsEs7$KYCoe|4Qi5f#3y8hS znv9S6IOn+?0%(!iZxlTNYx0BD5bHuv3|amGY|!Yb?(kUqO>=fSMIT&)Ps@$NHuZ-6 z+WC>trFLJS*&kRky)ZSvUtAL-0C=H%f;%vr8NmnWL~2v{N)p-6=Nw)@Lp>sJg1=}l z%SqJO=00qno32cjda2PZbRLAlgZq+~G>bbwVMB33D_rq@8fmoYRQ>-Qh)~>*oApWf^zcSN(NmD6*nm4@0xe?alwdfLUt5(o`Totn23K4NNX(;f>nw?iQOhQ|zVq8%m?ebbDHuHapm)goF= z(}koM*5q3q5^>;V+#wpdBe7UV8U9iTVFAin5qxA>GS&%gztAIZnqbV18mpPZZ#84p6$A7ytK*wh8Fk`V$ab}_4M*BR~???pz? z8*Wd~X@S3qC=HW!bRNKqyviB+iYh>q$Ey@=zh8_O_4VRAXIoyE!IBM%lz^bO{1(kM zRMg;34u{^sX^T^Kyy*%Kk^N%nVR8=QV}co=KFHcuJWTSZ`p+!D?Oux+Y{s!2&#>}# znotb1W4|)33o=ahp8VNKa5};BB@{IH0(0EAW=4rvAq9?uzMxf$9$v&z$?JI*Tosutz8iN& z`NkcOM-C{KRSDbR$|t*B?(?t9HscfK{_%#o3hOA z_|ErWAdPct(Mi|c^6RUgQ@gd{jlNA>B*@g137e-_Rp!pv!?gff`s4QtG9csn=@S>> zMNn37wm2)1JS)uM%TpoBv98uxqh&Nm1&PRiA)%9a7Kw|8TtYNn(ySoRY=CfsfT5p` zBcS=+e+Qb%$)D$Uf1mYDem2H4Cud}yC1M2ew_Z36kBybgflIJ%;@GJ$ZbDI7=Iv2D zJ%*A)?g zuI3H(|Asw>_^kL25SIM1Q7bQSh6t!{xkb>wu@wX?wG`C2i$v;K~(Pl7X z)@1&=7SUA)+^&WQPrNjucnSz6*@HDRQ)1^S@hoo3Z6~vn(Uu>y_*9?^{5Zd&ECM{! zf1cWj@uC>&U%m+4&nyCCwxF`A6h_Jf!f^Ig?%uL^{m)|lGCdeaJ6lW8)D9KIXoxit z0N38F_HdpB&Ej9N7b$`;F$feQCYitiu~+rcmCJPAAB9%Ou(4z;_L)8ZD0MzmEd2=2 zOJSD{NmCz|s%5A6&Q~yjY{fGfaK5M%n>qW%FPKl!l`bnNba1x}4812B`GXuJ1+o}5 zXw5m%nxf1XgPGawNY!#EJD>4CLunE8CC{4w)*_RG>ttvz#*&RbEM0d#sYHU|4hlUlzXZ-Vg^#exQ3 zY|x5=rnJAGy_~nV!5FvkI~_?ehmhJuTQsduF9<8k1J6QnaYy3tcet_d+dwC6QZT=e z$Q{-F&vN&lqIpe7`O>p4>R(y}+v*Q~OfWMUuwdvt&+Q?|I)Nn9J?Enc9)9~y`H&YK zuEQi4

+n_w;qJ+~$XInO8}DW3QD2q%MQrJa*LNE;)H~bG#f3C51$sIRPgy`$$-y z#r89^h7(`UOJ_Aw#-&(@ugUH@s`c|cHM$goxa94%*1n|ZJi*lON8UKs&Wb!e7zitO zR&K|&-n}k;@PxfDj}zs+mTua{supN-Iy6OOQ3k#YtJiX6Bq=`Io2mWS4!y8xWDcke zx$D4BYTU6ph(H5^^$if7{C`v)HDQ_3@a#<}@o@AwNm9?zO{s_%J&Q2jv1 zI#?`Sq9Ci4vonemxM^+o+6@)rt70VJVe#dQhx@4_PB@+qN)kg<)I?vcttA#&cs#l} zC9Of?@Y|Z*o+H@p7Q*+Bjmb{yhYYj9mu391{qSkHtedlU1v&|`1}53~@=Un+E5_28;yqX@#i;=nGjoDp9x zzR#`V(vdeAC0^x-+*nc88RC4F2fiKdj69NZ-K6sL3aA~);AG8%P*6-X*q zvV{ULAN)~#hM@``xkG#m&pO^Yf~C@S@}K3gA=`nLv*Bfu((;$Rq|Rahq3yQ=U~-jp zn*$Mx7NX-P$GFc2iKp$HD8>;DRss)ca9;h8q3pu#Xsa@G)x1qbFs+ zMlBSvGaBTy)Jlr`wQFi+)?!T`FC~RIh+qruK_-6$$K^BxAz(oZ1Gf9cs(jDLSp#p_ z@XOVBea(%ar7Dv_U+m<$Ni&t^{$6XTmq+gjrMVmU5XIiJHfD<20^z0pKV*+(GY-$R zRtj&FJ-k*-aHcjm2O1EqTBL2~{g)V;|6?Rl>ChVe3ZdwITC%^R&DVfW{$Iyb?9U4J zGh1CdD-YkOVe67kzmk(y;K9n*^60T|y-8&G5fLA#Vk3A~z+)r^|2_PXo|WoFxfk*Sq$|1%@LyIJSEUA|c$o-R z-=wb(!Vkh;3?3fk?$a&zUyJ2^rnH4Z!fy#*Hk9aU%W*kVz>F@pZ@5NfG@RDEGvY3=;_R1^GuBiYprJf z`qx`Z;~bB_`ZJHAKRkY`&`*hR_K?2zGe#g$Ec8BgK&bkZ3GpPU=yArh$gluJb1{zX z2mjnRjU||`kvTx0!1)i*OFQxMKvqWb=?d02T0zLv%>)w|9C2dM$W69h=ML0RUUNx? zrD{+baQK$=GKuF{58ua`LG}FTdlimXsl%qWu-7xH=yl!18R%ppwm=bgonsJOY!ggo zFM`yciP9n9h4x`6q*I*i^MQk!b$RDgv6U02XExo|TRx3N^X68+PuTwSW&lpa)KihNWR^plp)}Pg zTy!ZX9yiJ4gol(kIi9}l<*WMIF~n!#8Bzw4|sv5wi&dkei?dUaG5=j zEvDj&hM7$2nnYgZtue#bEq3@qooUZ+q94&MnUr@3g* z)|x_r0eh;O6cNTE9XjhJt>Pp5N!_$n>tqK36 zaHY!C*VsiH=SP4*PhDg@0S0lin{R9DVWQ55DGf#X&HYLEPAweEP6~Z!vus!~R!`zs zHionFkFS`n5uI`0iq*p>^`vc+&VD-5m<|*h;Rk5JmvUfu4O$Of0V>hf#4yjd2kTXf&TmD0KE_>&Bjrje0X7L`5dCv zzGAB%8Z1UN)hSknpQK|?7emfW&Y<=m8$I9i+s&DofWFylJydBj|Dj_2a-!4^FNf69 zarK5fqmx)CP(s(GluB^0EsOm#5?d-9F-@wMjf(UXbC?W0zG&>X3Vzg((oFv(DoTOlUrTI z-jK{a7#&t!LGU4lGwmjftu{;6OA8X0A#sNeKemW-jtheGB~&tWYS4SHOSDlEj;5~> z?di0C?xK`bMWM=Sn*jZWI^X-C0a_~0gndR#S{nBCgffSaWGI|d_VVk7ih~mrpE_cd_fk0df3(&I?u7#&MfROv5Q7 z9EH3NV zEDfygiGvDRQQ>aVYSpsgC!PQEN|p{x_E7t3A$YcG9x(cukibVt08a`hJ(Eg zb6&?IOX@{ILY;e;9b1S#NjEri9H z-H$)OShcGbr^;FR^K`!DDIN?Ck_v7By}TzHGN5!oM)+QXpBi!Ic;2l0zto6-;9?d? z^^AI%oI|S5gt8=Yt4J4idPO2~MIb4S=v|u&{9X*$q zhQgDgZ;c8n5m7j~ohyJZ@E?0&<8>S1vXLQX8n90XnL1?EQxJyR8Yp)j7RPg<&(z|q@ z$<7c>oW5j7s13seR9%`@W9S;z=4`g=f&#xp0J#nMu$BXqwaFM;TrHK-^RK?0vTeaZ z`CD`ob<%H1Qq&g_$2WcY(c#9wJSl@A$>VaoNWwJ;jR<`K^k+~<8>fglFYW3WEAI)H z>SEA2Phx#hg_W_t+l)<|pl}5gA!kR@Vi->ir>Z_eB7Za+0IRA0B~7$uue#`S`%Ovf zW#?f)Ac2?exn1PLZ-`-S6L2_Z@3L{M8h)@n>WG^2sr}sY%J8JZ%VG3ssCjRSn#SVi zr&z?ebwAicq%`%gkgybArI=s2y)&`#5wIwJnQ7!2{>B!W)m~AwR_c_(2&x1!g0J$D zB30y_mz~pB0&>@EuS_v@Ap9mkk^k0CB>k!tX}K`9Y9X(938PAuM68E|OWk1l2<+#a z{)Mxa`-Au5NgI@-n;9D%&XTYmaVg8#Kf6Ky;SpUr1Jj~eU&)jk^iGEsN!&$2dQ0?W ztfi3aI~|&=X2rjIP=Bz0FBD>OE^Eav2RX>MfM=dSz4DQ>|7<*1kp`{jH zh1o!9t%F{S^wm_lhzBqt1b}3Ll*4deLMVhLBNzNX+a5U5M9E*O`lrL0ghDE`#c(KS8M(#YWTq*~`2P+)KXHIaJa|a7PkU zrjL!cEMY00jIfmK*e+n8>m>yj>r{=acz>3Z_>7cgs6gK;a2kLII$1P}6ML~`*p{J6 z$s;{)LaYy~!_q7Mke?lnqWgw}IeZ3U9-tz(w(0GUAM;5MZfCu#7~+Hq zYt*dtiM9SfVhtaFh+AEL%uW88r`Ke{Rp|~s3p~;}>YH4C>IGpz?3B0pDwFQebH44w zs}Fm4dO=!{oez94OTvacq|E#tupu|4Eh0fTovc9KsAxEJzTRF*n2V7s zl*l6BavppY7Z=T(7EFFzFqps#Y2QlzBMu?^rO=BoL~_+!Lz)Lh%g$23%BPrMFVmgZ<}Wlr{u~%M z+%_a)J@iU3*|CKw0l*>)t?}zf=R>*>NwH=Lh_(a(aopfmnMvTo*Dx|>Z8A^u!XN8r zR^gFA6RwO%_Meg{sAm|i$q@JONXb6jn>YFRbu;&2r%Hd$=SnquyN^%FcU!hsW__DJ zlSS=VevhyVU8ElyiO|jMJco8Qr57m^mI1q32#Sy{LGq{!5coEM{V;Zeda22k{F}g4 z!p$2oa!I*|L||8t8=>K(g=2y+P~hKNe~k_<$WJz+E1+ilA3+Do<;*G=c0k@A)bQdB zW`Wx{2^wJkjPoUR!b~Sdzt>-XI(f8TZQGL%j?;qcsFyqtu&K;{p7j6QJDmkNhDdfY z%1-E4HUG_j1Bu?~)@#EjR)&I35w*SN=$z`J$Q}b+AnjeoTZQktZHfvYq*|uvm>Tkn zflnvPJ{q*|`a*VT{$({ZYMO|eEl2D|EW*ZT(+Rb-XL$G%@RJLRb+;F^X{ByWa?`AX!*#fIm57)pYmp31iYn(2T6V#P(K_)x#3j-KYC3>CTkoE zQ8U*UX#(&4Ara|cXmFOs^z{y_#zQM zwLC#1L7Gt~uX`Ewr~=|kb?y!(FipS=*NQC-Qa=-}=ftlVbv~r;*(WS|)D*_IO)M zyM=(5_unHdfZqF<Ep^blpV|Ylwk@Cki(J6+!seQ#(Wv2IJGi+QrJ&L z7TOmgE4?{PBxqmvGjRcs<~Nvz@Tck-yP_qcfMY&pW)&69=N$TGIxeQ?^D702M~rUy zVu>aQ2)@@uy~kJX*sJG=iKF8u-Tm^MTSg>R?mDiK30x}&0%589-`G-Mv})|YWRXW$ z!ANmQA;{jMKs8G)iI}*;ngI4Jx+>-M^{LAhI0OOt78Z~Hz2%rt!sIPz*D>QadA(Lj zZfGFDZ_;>6a6Y);fw^6Cjq!PFA(x@654t(I=z|}!k_v^*U~eSP0mP~?qEaJAnb{>qcQT0TDvQB7di0DyHG(s8Nn~_C<)>d!v2KejzH<86X`xPDoRF{$T(_FS(nRTNbsHMx zZ-O~TbgSqvK}kE@_+q7Hpl7)LAo5Z+!0_dTTcmxy_yhW%e0r)Di}HX#rJ70+y#x|u zf}4so{+EiG=J1roojU|#Rm%@IdOhY}KpEbeC8P#|5>n0n4=4q!q>PO;ptXm;LuxkH zKk`|1nH3b`MLa$JLN4BT_U`4Z#k#+)QDxMQQ{U1vd`*t3*R%px0GlE*5r(yzl4QE^ z#O8{?>-rhy$9V@s5zhz*jx9|}o^-5p1k;MGR1_QqT?Z>;_KOyIWs0r>5dr~hKTiqb z&%gp|X<0rZ(;$q2hu++8(z8nBbK|*Jeb#tKf>jIeMB(DXSh1fEB;7D(|2jDT5^tt- zIyPXO0NGef%1BPqjWs|IN;Yj2^+Dn%1p9HqU&krcumpa^j1}?s*o_zT+`9=~F=xIi zlo>e6-^`vcwSXMHcj3&U`?0g>WYnM@gc*s9wlLQb=RN|!Mn8-+GdLP+-jP17GGGWG z!;zyiSEvCnR|CnTQoHRFoD$4H33+t0v9XP~PxA0CBX8>RzUu)m%pNcI?n->sqk})S zVBHU1u{)T7nhVxLQp*V_ZC}|CcMZ{LK0ZvKnq09vd@nGnL?}jSo@@xZI(GY1Wh6Lm zKZvnoSM@{eNb?ozacxwDVOYmF%gt!MbW*`S0mwyl*4oTMrL=k1kt>$b!@KB7d#MXkPHm;>ZwS-WK$_hU_SlG(CWs>9^r2$|RSNLWjZv#+b5*7NwdeJ|hIRBv8WY}_R;(Av(M_K!x zn;{L?27RTvGJ(CXCD`EYbYP-C$3H{S)0#KJAR8F9xmLAzKVR@nXTg%Jv$N^*2kc+! z+aOAi$2YRKZEzVX!3(;;CRyShL>R+bb=4H>FgSjqz{{9?i~EcY5!K~|zS0&Dt4c-< z+DnS#!vxqL^91+R1GlnMtd~M5XKGPcM>E+Ss)V6$w|fb$i$YHj-ikoI5y5wJigAA< zG$dodD!c|d3@aJ~1Z5Ta*Y?1IQA)rNzO<1mpVqe7%q|#> z5=Lf2?C!JKuiwU5YP+8_ps@JMj{uZL@SJq|lKeH-`iHY0KCVRExsSl!$N!bJdU0vm z<^@P=Rj+}L6<ZGeQC{>pch9+*Vp(YS&#VJ2cfEf`bl(&$|U*E4u$$#%s^CA#2{NK@K+)8+u&vI-xlvejt0Ql^yQ(1tyI9!Cq#D`iuR9|muCWb66!S>aHV z&aY{9aVl$658;pY3vVp~OAkYy_r4&D;G-1SB4Avl2U`RnGj;MF%R8|o|86$m2DUQ) zYOe8ykf%ES%3K?z<0Ne-Yj6H)W-21!9?CnR{L5?QPbfY9JhA^@Zl+EE5orPY|CrAU z9YG959N*68ue$hx#RV20r=N0G=?-43cmUx^wH`Hm9#5&4NV{v*DSWh0u%t8j+}aE| zC?5hhQGmn?|LCRuRX!2A+Mnk2hQ?^vrp`mOeyoDQVLy!7UkXy-z~@P*{76y^u{})L z;1iiPI`pHHQHu5IGSozOWbOGVN!JH}$m&`p)TraMt;KZzh9A7t(WWe;6~pX>RIDdO zZDOC2Ly|+NdQ1_&B>_W#a#a9xLoM{(oNtocBT2rhoKMkZ5>ZrOx|iReYSyi?@zfvz zax6asWL2IIkuFcL*14_2gN?<_2uE!H$j+pkNw6KM%VbS}_9>+T8f+~NUg17R7O-Bu zHD5z+j_H+*3%)!t6$s}h)2K2C8}`}^1vlfJHAO>2&98n7wt#nh*a$=In*lvwi?vXD ze&>~SyVttP=+91C-S5JH?7?sEOSv>nrQBsR6WwmTj*?9Tc zl53vMCF>(zUe68K4eZot-S0b|mz~%v5}wEfCbqP0V(pL}>Y$)(++evl*4l-h4yJ6~%&$ zVP=~;X+sQqhNZIWAbeuSUeQDA)7cz0nCfp8KUf*K^9eD9K~{kz!lJH`C;f2f>kr+h zN!%kHdN9lyC|HX_Z)1Vv+WgPCGk!P(n@an|paRw;5(x06(o{J4(q#?!N{Sx#8yknd zb~4G?F1#*L9pmFch(hW;j*d&sOKLY*2AKd!Ktu%q+ds&@d!@>z4FBM>9^J2I=07H| znNA!>4~{>H3FUQ1W$vy-l(>Tq#N|{nlX7To6J!6nx>X=VHKXf`x;{JRNoH$fXneFD zb$c={XLlv<%}W`jn6gjNk$aq=h17*%G}4!BrkkF+VfZBgEcLT!e94+RG;ZTNIlo$1c+1W;P@8WKbypwqyFDQ_EbA^Xge z&>oXnwOA|>^s*2wIrW}FwGvjvv2M)*{1!rErD;t>WC{JW8EE0dABG=Z(8)gKMXda( zl%4lb-U;QsQvMF5j0Ga@{c2nOGHbf2E^2kqKW<-z?jPi@F!Qu+BUQOn`X`hAZ<{2O zyD}|bk%JoI)FqxW2*V6ihT6=>%8H%vc86Je8Ma8%A%Sp zY-wizFMgvr(RndxCEduOiW_IM~oyi@De{We&(xpkEy`T!e0|YHTx7;8-eFyKgfHZWD=Kn zv3G#xPG50PYe|So-|@zB{_KQXmPe&$8VLSN?e+NBQS!H&&%eZd1NYjH2nkN(CQSuT zg3zTk{A4mB;y_FJ-Hs{=FYDGptNU&hQ5x0y+u%}V6LJ~M2hf~N(XGTlxMgGTJE$@Riz=Y zc>`JjC1aviW7crFEtQBd0?k3zM4aA=*WY*Nk5#;M56T--dg2Xsi;+n_z`N6<6qE~- zB01Q+7a)@SK9_Y~7%Frmv2eq+*Rpb2?TO3~6QHU8aZ*CgCzc1txyVmdoo^mrea!A7 z+FB`rjAw)m+B5BvX^dn_V@@8ts&0Ek-P{cauz%l+97_F+o-lPFhmB-XEqa54;|X6a z$B3hvrw09YY6^6x-?~dzkNl{dA)6g&`V<31io6%!|5)*bE6#QTc;Q0U*K;6_S}kK8 z6*S=mndpZ^9m!Tt5wJ=IF_rJpSk;Dxyh*b4&V)?xLG${F(_4q#(@7+lMce#=Nu|L1Lgqgg%H$FFBxk0mz2d}sDL^E3n zWvTFiW`1gJnFRE^z0dJIuA(ue(%BnTT&eJ~gbGz1CNtRdocwaipZcJtTDwOW-=k3> za*H|323?hYCd4M zpDu$2SAhpA7FW+mpYn~u=r?z^z;DeJ>AZlhb3Bzc8s7AyW82nJ7EAjBecxRbTyIFo{xh8~|lR zYUN>Jrn^LP!J5_eHP`#;&av1Hgg%E5`|1ZyZ>N8FHqSWwHHW%i`Sr5Pwdx=zfDT(> z7WnY9sY`GH$tvlXTYFZzqXD*CAJdnuhqNuSby@#wC(fiW3R`0bnovzwqPG|5RVH zXzA1UvCoR(lB(eecA~(mJ!$u}JkLc&8k2RMSmP4;+2n$?=Fi$n7%oIM=v9gl4JFn7 z(p4eAXkt)$7*z!mfBMawL8_Cs2a}0zZeGvtYv!L0j3XZdo07OZ+Lv8;l?vl;t@BXbHZsUyn;-B=lV(EWooQ1!v8~oo6 zv-MfvDL1r#`4nCBW2vaN$f{qiml?fjGPGPKi>O6Ird*ltnNcu;$dV09+=(BZLG;rB zTdT+D36C=D!Urm8Rm`1}axIeJ%7bEaG{s4uU|aj{a9Gy+RY<G{tcq_ zCM`mD`a)-@K8+7RXWwX=4jUR%hyXdYyj6!blcFpt%lOU~j-IixvswHgBY*b75M$2I zOwfVjkzsAQ0Jo~iv3GI)RHJO*3zNc>ie2$>4m|YReRGt?JJ9^+5Fr15^yRp>O@E7R zx_OV}y>0rx%e@E{{hrA?nY@?D-yxHzJoiZ6iRAqh{x?kFBY~)T_e|c&i3Yf5@=hl2W%75(BpU5Kl6N9` zFO$DPCRc!H3IL2hk`>%XL->yiYXpvlVBAKGV%QIghH&;M{7COTzZTMR4Px)c()t4t z>&OUl;r8>#OrD>Txjz%!h)eu1lyldoew4uE#e}>ejOlC!^KkCRa(U6S%X6KZ?qbhI z=?0A0BHN3sH!>B!#B z68O*A^U&pfZf0`A8tT@I8}vGI=kPzeOfZ z?~%L{$$OdnJu(@2&*Ys<-pk}~k;$riB=1D>UM7E!OfKFtc_)+iGWk1X5(EAo$vcs} zm&xBElNhY`Oy0@ly-fZVnbf#P@=hf0W%BpPq}M%@cQSb|lmGW+at4TzcONn4zl|94 zpPm2Q0G$84U1&t;ngPIj%H(tN_2RN$5B90~%G-u3m8F{=A6t2V!C5h46x(Gr<;zVK zN9v$v`1c8rSXw2q|C@85Cj&7Cf6Y^Qp97soWq`o9>Fd!s*=|rTHMx?1li|eHfpGIi zj9gOgArWcAv#1-P;iQFQg0O;TKybUm4lc+~Hliz_X8a%RBkkqPDj0SIJkqJ*#T(25 zw{a3QjxXFI&X?2)Go2XyUVkmU?bLp?ZBITpP7AK1Uh+V|rZVULTh`CpWR#R=TsN}MhYpBJQwX zJ>LumEf7@Nx6F2e-=sq&s2e39QvH|NDx-iHXaA--aPN=F`D~pFL><+& zXEtZUHV2VPIuwXVp^b1$81s3*j*la&Z(gjCuO^L{s!xK@l0pyi7{M52VEu_>b1~2%`K z&FzAtj}cXR|2Jk=slf0GB(}12VkF%*CH})7bDN*i&7)9EjqGseaR_Um9KvJu6c`g; zq|~T}lgYO;+l+|B!nK?WSu|8n>pqlZ&Tt7{RU9QRPEbk{RJ2Fg(In)Fs|V1dmEbGZ zV3qWhUEmIp#APV^nFT|Y?!K;q!@716@U+-+cyi&q1IX@yc<)BYu2e#eWD=5dBxG$T zhrn6}Y$VPrhoVBj>h{ld*b0?&!pS=C?HvmL)_XLknm&$LlWPLOPVpwK%zoq(mPW6R zaHeP!5R?3#$^Y1VX^20Ww54W$>d+%Z~d>TleYIv-pS-&J*n?sRVNefnY@$9d!76}_GIHd zlXo(Cuam#Wp4_}=@=hl2b@I39Bo_KTlXo(Cuamz;C$V_$nY@$9d!76}I;nTh*R0H$u%HW;C=KMqKH(CZ%htI6L&?AiTt72BP?0kzOsup^m4Fe{M!?OaBebb`Y6 z*)c_ZDJOQ@$*-^gev*)q3Usmm(I19dIm&d7DD%}n_H^t(z0QXWmUF{8a&@c)HGMJF zD3tOH*AgDD*r%$}5ZJu&Ddr|)qE=(paJem&h%o}qJBT9U^j5sU(PQ)oh*8XsLD6Fl z5}8*-L$WlTB~c4mIq5Ef;NYs~1H_nLgwb8i_j*!!4&ixT&a~8!Ew7Dpc!+1t^XXl> zeq?|*p?|eePRO#+y>YGjir)>{6Q@auMkt00Dr1Plh>Q5Kn`WfBCQYQ?cE{x4tsZn zYytm2j!CY%TI>O5XOcdyd_&o>oKG31z<>`FSDE|bh{l*NqZFrBW={(HsmMb6LS&^k zhlvF3>wYFK0Mh&h(-8htJ!4n2L=?Enh6r1OdVK znyB~q${l<495Hcp{G_{Io^#8Hq{>~#H8O!~v=TC4ZjueHaTPdwy(EaW|RFW7BlA$FQZW5Vx z4q?)G${ooxyhkCwxuOkX@}zbaD(FUlwBgfHb*4MN6F_OrYe*1;CNRo3XiZGH`ly|%7ID~Z-Pp9_wXutJ!N6CT=gQ??iRfPjGtAQpA6X2#(00h5c z6u?gdV2j5`y)?EXV)Vi_G(z4$R9EE6h4Z*d0dy}k3v0Pd8ooybs2Sv0G;)5iYP4#D z1_YK%4@t#|J3AFvtFp7J_RzzFFF)g$7PIS73sZ-qxqSaX*jh0G99Y+>d4f2ewgAVHvITeNK3 zwr$(CZQHhO+pg-eZL`a^t=IRQ`+vMQ+LMgLS}SvqkrA8v6`(6ghK)<*R%9s?9KF89 z?8DgnJl>__U+t(HKmh*%0h%<1USHwfk<;tIWoabgnGw*x`_bzHXG1#Pm4VRi&LYG{ zhHC`c@0dncD0YMBg6$w`bEnnKXY}$u4ZGR;2v|4lJ5 zTS(JGY|ooBaG`vm{1;rXGE-}- zKoa8xO;w}N=3m@3NLt(7hQx~~M2-OOj%r1>J$=Q#n2RHR1v%^e7Lc=Oc7rw_|e=7X2y054oj0-P4E5eEl+djOJ9LM9um(Rq~%5his=vTmS{ z&Kn)A9Nq2lx{CMT*%5q~7<0#OHES%h2(bu2Jje5d8rt+^hf5UNe?6;BrOp~P4nP0O z%?U~rYQi8^$^M{CfbXps6LF;1U95zdt`Ushk|Pbqo1XoO?E(DpADBa%s)lpb__*r@ zkMT*0DdqS|0C+DZDCrdeGuD+V2hD~ar4DTEEdh+?dzQ7SY82Z3A!Qvi!sLzBc1IVW zp=OksD_Wre{pNnRZ1rX6Gm$}BUJ*ub$&s#9Xw#h?{$E%(RGE;We4df&&Yn^)KDASH z{&&piUHmuke{LoF5=F~b@R$8HiwWKZTsBn+0J!+&2ePFq2AE+=fa-J8t0qCBH?Y^*{5AHdSK@_J1Xpv<~n+oTg!I^AmnzaY3QxLSboZCK`V` zdQ$DtrO-mc_StGOh@1ffAJmJ0b@g2@;>*}Sb02NHJ^Z^cz`numgGWIWtF2zo2^w58 zBi%Tvx*I#<=*|w_&May*#pOlF8&)d$x5m(U>MYe$_A(O<*o(6;&=IG`KIe=7)E2d! zfdQ93v7{;RQ-I(r)vCnt$9^S+Az%jQMhrwEOndD6G3~Y`)aQoAhYgfz^emrz3zace zE20(l*7&DAh+gID^MXXa6;Y}U-Ll9zU-OIuo}P%BEp~bbIKIA>$n0wp^QJ`oDVCc3 zNgg+4c8~YnTXNcE8j%us`;6jer8#tP{t)pb?xey1k{(IFzvPcK3I|4TOKY=xz%*%&xV9fKZ`I}ASNAA{`Wn%gu10%f#i`GHhV*? z9^$}iH#wT@31?(#y7DHJnB7kp;I{|?>)3>)UA+shm&KmOw@> zG52vzJC^C`bof++n&v<5;!(t8OG7N~1|Xo)Th%EkZI@DhC+8A=iIXG&ZCchJ2J#vb z5SRDFWD;;RxMFP-OC?~Cnz3hfY*f|`gGD5Bq_EAeb37bPG-up@Dg5YlN7X8X=iQ}= z9<<6PGro%zox-!_?e7nQVz-z_-80_S+@lgoSPiFaiB^qg28 z`ya*N6m5_2vJ=JB6uLaDJPrUrzR5{uOmL zQ1%cIRPX5=@R@lg}0}5poI$d zcY1Jy4>&cz^czHA(!H$q`~DWkQh~ETzSjv+?>Kumkw>GaUmcRYhLfqJ0x+6MIFGyI zaUMpKpL^ypc=+o3#EgkE45BqMS=oH1uS~DyLJqC=_<$Nvwj!KJjQo!1IX=Jke^gow zWC{8PIo7bxEde3~8?u>eJ9p>I>Ab>2$}zTtCn)OF`)LM>ywpORV@y|x)m@Y<$8DnHBnqOcoZ;(+l||*eP20Sb;dHQ zm>ad>id1J4)2=<|rW}f9_&L8t5VSmGafK7F)VXfj(F)OK9jDCKB_8o;ng%WrNCd?U z;KX>WlRe#9U9@PNa;(rq9BfvhywQ!=Eol;ez}W0X!?~`%{+9cbKfhrP@*}F4vn=Q8LagHH*XLaQb4IIFiLe5RWx)6Gp z$Bi=pV}drOc8yn#s)DDlFeQ+3&t+CFiIj@fh&xkvc>7m5c1D@v<)_Oj*SR=aNA$* zyP+}b5}g;&V=ePV@5~;h2%|^rD*Nb|KR#?Vv-wh_4zR~R9vJBjjv4ZumTOjoXD4p2 zGaUXhdXXZs>*Vhv)4yE%2C#E5Cnxs#FZ2p%ggR;d0TH@MVstD83|Ualu`yy?`N@0% z&ytIS1B#$LtJzd~(J|y7PMR@UPX5qTOV+&#Q#FmPrvtepKV3xpr4^vreeh=K);d{} zLDMqE42%azngu-aGr0x0YGT6|m3By347{$vixD;S$b#LvaAAp;_kPZKZBkPniAk{v zNSjuX^FkT?C#aVlwb+wYysK*EgjJj zDg~Kv%6)0-z>0iB=yN1t0L5#4J*qo=qDPl@3M~wAhJ-%E@NricoQJds0haMuo}~*2 z&>d`)dFXoBjiHNK{#4sS#Y68*Om{Or`ZZgMP6jP22|d_F%FcOMycS-j0Zdhc%60`e z$)8n+?FigK#MF$}wLj1ECqDAkMyC}GZKGU4_D#G+eP>YINS{G{A|z1Y$h+^!a@MTO z5_|5*>OF2cfqTXG`Z+6ihH+;{qRFG$;qlNz4&qw(prKk5m2uZn&4^^k!Oc;Ts!WL_#Bn%TDN${C z)Mr}D@O_+IV^D$6A9K1iRXT8Wp4NU1Vhm8EDJ7Km>*2T5uD=oiN7BM`|k;MhwK5rJ#M0EVQLudP-+ zS-=r8tHM#h`(C2%j)O?cYT7P*7UQ7;M~>!j?;n9!G><(d_y`Dm(-L`B@HA8i3)S58 zmDDH!eIB9tgU}k^r^AL>?Kr(VC%z@SRf}77(1DX})|$`NMGAm_z6H}tP=FYdoGhlg zl6kA8`v#1(^to&LQ0b;SkcvbT^Pw_UkoakoDYiKw|5Lc&uV>Z@~i=VHkTSX zX~1!t7HGT6S8gb-kJPDD`iRMI`?fQTLPwkGk~R0z`8H#rax_9k>;P;FYLO_J0IM%% zvp7>V3{j#eE1+AcW|{}P%(Z3?N$-%vc!5ct7cA;dbc+F0_JJv1ws;d+R|yG=6$fWg z7V`|0YU@#9K(O#g(Lb?E$$yfl+;k>b2w~;s6Y3`GO*dr#E|}*}!;3pP1y#Pop)`W% zt!IWZeg_(PNoWJan@jq*xwiCiDN{jtYiOWgE2rib?D#O%Ju%y{cpaE+a43s+NeCtR z)eA0t12|=S31myLHfj)PHTNy$`E++Q6*2wQp<_Yw6>ja;BH=)|3ypvar^2|maX4k8 zgGgu|6U{XGLSEGlLU1?l(5#|T|1~|vIv^FM)3r!Y*!p3@$&(9VTUPM_xvJj$~=XE46L(*U~u zu1QQ-Euh{4bgXMA1e%^d5p^z_V(?s2I|QdUt%zt~5P?gVGvmqD2WwA8ge*MYJDxEseC_hlOe+ z{MaA<4rwAeOo|eg{)>8yU!6Hw#Nr?xf_3Sv6DHeEf z^6Fm)0|YLT0d%%?hXDAsxr$NJbU*2p`ss+I5`So(w6ZXTF)jycxhFzx`;9cUKPt^% z!bOKv`;hSnpG_^(LIu1}vUu(on|-Cgd8njHib<7p=MKD~)XC4kJ5{#ehXtW_0YvCv z`~=ZdF-==QH{%An8lYQN;bi+hhFOw`8%Ca}HOvg3P%c%+z=nBSmze7Pn(6nR}I*V2^lZU z?aZHI#@3|ZbZ*~U z3xXfzF{DtxBp@DPobS8XFm-UDQ{p+mNXrD8y@sDL-<|9%U-G?>*U>vI*xC88s zbSH~VXh?}&MwLo~Ssq7!O6LA7dv|t)Vc2yopCvJpRWKH-m);f-?$y4iuLAU- z5-Q&jt@#N_2ZGeK^MtQZ+rsla5AFZy82e(eM2pS;>EAMLupv{EJWE|lc4f>J zr;o8GPZU*Eb>LW%f%D4Nu}59$H@feZ)};xM-9E=jWbmxdls`T=-9Z3}ZFLo$IMR5q zVh9q_8l*@sW#Aq*6111D4rI@z_9_5S?D!c7-~oV`1^|vg0)Tf)j-UMv|E!1TSMxbW zeal?Z*W_RI#P{v~4WHuw=LrAXzk>e)|J-Ncr*EYE8@~ZQgH7t!=2!9k_YV9yzGC;D z-`)%FJNw&w_jf@4^7rD`oww2d_jlzj>$~Ci_t$>E?+yO;>tzku*zoK34je{m)DO2LChglK4jO=j+$4)IZDLiIY=H!N)L8 zcDj|Fd^{rI$I_5zz5{|WSSEsf6Fvtwg|qcb>SN-&a-;9Ut8BEz8EOaW${oqY0<$82fj0*+3__X6w1U zC2&JpR8Za`U7L-eCDz6DJo!vqV8P_FLJ$o?6;Hha1q(0j4w~|Cu{L1o2SW^{;Ro~b zM!0EQ(>x~_8_=n_6Ll_ECU?P6EkQVy?3$8iKodWwGIaT2S;DU)6#%fGW%YuwxVC=t zFY1%k;dh_60+`~3-_%%Xp5_BbjnPte;0T_X9bchFS3OW{sw>&)@bIkBik0RV?g-(P z1L-<|rqm-tdvW`G8PIn;-g{*Kyh$+Gfiu}h4Mq^NogRW#q~=NeGUvrg^YF-}F^(Vx zqV~QMXQmw$vl_ON`HR&FCX{+nin`L=-E(P-l(GXy*;}`*RlQ3`?JBwwo(&=H(BVxkWH|I_Ic#&Uz-f}vx} zu(Yqn7~MYr{|nVr_1H|$T?&Bl0|(Q^KcoKzpa+a9X_=exU?U}G)F9e3pu`zWu_7S$++c=^9-!# zYK=wGBn+35ijrr`vO?=CMpoB#kOld{zM~41AD#2JZ);L>BcaSXRI?a7B>bd1?Gn() z>`Q+Frr61xC99~kOU{}mW3lLTyv+fE?U#@n(@rNHb#H}ypK9>57%=6fiq_y|e!~!? zxF2o07;|u8nch8t6vbww-O?Khj^}D- z@7x2&RF)+Yo-~0Z?b7Vt7PhDi;Mhq0VBC8NQ1|3*BjoiaoyQrVw?#;d2l%^~A=EfR z>Fxs;et8C;xVzQdw1C$C;QfiMy!iqr#V~qN;mC0>{gwAkaQgL{o2L|!baKBk>G{6% zderxK7&kLym?k_V5Ze$pZt+#q#3+WRXJRo{lRkq!%B#MBW`H>4d8 ztRU9;=sJMukY4*)Z)kj(B%U<~Q8{0v)7~U!^ujm_R%%m9)5fL}eWZoLO#V!=6)6T@ zwY+$=4l;h?^o5x`N1xyl*PYeBCGK=N%mcKm_|si6W7Vj!pqmX7S)=!l*$`+xa`T}L zp@EtB8yVM9;YU)ni8kD%K_Q;YR_KzS>_T@>BXE&b<(zSQh`H@MF#hxVw}=HV;gf+P zkdY+oa?Sz7x)$?Xt~9v(jC;@OICneK70=j2C}4@Bk$@zuk}gijqMwFKrikYLvvI@> z7Y!1`BMsgUZAMd+NFA3axSusCuQ9?YJ7MS(8<#(9ZiYg|^s$8=%~9_|x5Ij|f#)xv znb1oxA}DZxw%IoQ4?or~C}&$b%9;h~utz>>G5O71noWlNJPdihy{t|H#qHez)IpFbet&3E;HDjx_JLW ze%gG=qZN-D@N9}Q=smZgSrp)=QC5oahwz1qGGzOp)!8{chySq>p?){2=Op2s%h$B( z9V7S->N8_@1(K{4I)Y}_vQ8n6kVaC{qG9|weC3iforl z>fop*9Z|LjqE~Be6&Y$CE50TOPc-FXqFwLi!a_sPMM>Cq(6M}i9%y$xE=W*IRi^Tw zh-TPQo=b#MJQB+90>ax(Q(B&_JfLj=gl;Y?XROvuwnaE4OU!irpXeN*T+qb5StE4^ z!QtV3lt1fH&x#4KV6vpX`}OZnDGv9@wXyc&J-dqZR0nC&-SAQb%aNedSI+dRuK z(;H1SV-on5t>Prb>4dj8DV@>U1c|4UXlA&-vTaMC?u^1gA{(?1j!L%$;CSsInBpV=joVI+l)5HM?et*OM3%z258~2+ywF^&tz71|1*+ zUUcJTImOX_z42h0nz>{RnzxKEv^|=4)SUL~Y0gV&++s&2%jN7w557eWJ3kZ;aov)H zgT^6a5JV+dNM&TKQkV1;l~*Yx9w^HY9Z%N?;^8OBB7#s3f8PWNHCRud1t1^HH$<1J z%hlx|Eav62wzaql`Uop8;LXHxG3bD`O`3~A=fU3no6+F#@gl-f5bMoC5XiBA*uU)G zwu@jfeFZAN|Ndn#l?zPL<^V<;#swn*qmAH#k$};&2l4=|qyR_X++x40zjmxpd@K*7 zhJXXaEQEs|C>$jX2+5na_JENIcrzeUJSgzc?g95}1nEY;A2bW$pa%=bNCQIhW@Dvz zQ&7WfCEb-|wQRLB-C;fa<|D4+Km_!$F|+fH-eR8@KOPg=lrJtrVK4*{E34kNo_xMX zJNG45n>Swant*BU0~)!V3dRBRHE|puLdmt%jzxi-U|WIBON$+it|>Z{&k5kvZ3i>y z3@`;hMv5a3M~J%Uju{0A3BW@Ed0X>Xi|-?5745Q|6xdBjKlC(FF5d#!O~oHVKM^|e zg}`!IuTIC8umxTl8qZ_D_t(IvAMuHIiy1Y&;!sLKe~V*yu{}0vS6>MZRcf$3w7aq! zqXVx9(mbl*1wCe{hK}p4Zs( zpRlR+iTyO5r`-a_b67!P=X7z*J>Syw6-Qv!*)OZDHnPR5P%0Q+FtjYwcvve;IV}}a zCr=vsBW1ZVEr+8i#7fs-z3yss2~jG6>*DT*f3%K}#LGQ;x&k9bW%GtI$SkS!w+~r2$Db56Anogd?0}s90Xdb64rOPK1d+Z} z1s=BIUO2=sW+CO}nv&(xG%$_V$IGoKMm(;AD~snIEOiegJud+BZ08RKH=>O$wZ-@c zORYZ;hQ5?Aq~B`;rD2nN#Mo-*10b2vUseJd9OTY&NcfJmRMzg z*sipr0@MsB7|iQch+cvObMRKD+{pj-tlq3eY2asSpHiKQ*GQr6y;&icEYQ^Va=Ld! zma&)tb&2U}&{ScSyPqiWH@g7{gvw0?+EF0_5!f0ooKHVPDfG;F@ePHI$q=s6I zq5WTN_c?Pdj)mUsPvbP-DhhB^Qh1=6HMoT{Ugnxu4!u)EeJz%~J-h!bF> zK+py7@{rX{v3epu?Ro@X_Fjf>{lH|Ia+RAgf)hS-TnmEw>&;?TAZ7`e>auIE5q&sl zhde6AlKs2X1Sok*5I5a^OpaCeCH8}zhe&3$2=%{*{))y1++;kgo%NGKX-ov( z5%8I{>bZF@{$;zD8w0OeHXt`N#AH7VurP<&&=qzM>5@BQaLR|~U;^?$znY|Q>n=z4 zAN#+^B!%!^=tc44gB;on@+3zS4OB6gs1Zgn|^K ztg1tyj&Wy#ndYtZ0o#By2&Ic|B;B)^({=TR9Qfr({VNz&bY||8v(2VN7#j3aR;P9o znck<^!|Soyg^NA60#BBIruwAj@u(|PLrhy z1khA-N_pemC)DKTTyDoYJBv?6Py7QC_Ek3<_JA*(1y1JaAe?$iZ*>xFs6Gemsk}mM`dt%aIEFsh)why{%O;*BG1J2C(9R)U>s*VAXJMLy#@()D@jH4F3cWK8c z8j(O_Trp6@UIpg!;ZYfvWe8xO$z8zy$h@}&#%SmIWz*Bv*AToIokCP&Gb0>@0*H)F z@DYr#^{TN)jjM{LTR zO9R0h2rB(1cuUZ`RKNk zTMqu48}yF-$0kW{Nko89`7MJ2;TheAd~#DNQVI3-*@psojiS)my^0+x#DV6boJJ}E znx-kG>+hcd(U0?c$T8R*pm%EKFt+To%QQKg1!|=yd3ti%EV}-Y?E;YVdQ}SAw3{{? zPsi5~4f-r{`oF#b`M{BN?LL9PfznJD%al{YV9-9NTF)SpRFz!%P#Q@PD_bV)K;ZH?Y5sj&$bBu5toF-Xx#N`y)ta{RVMCRxFkU|P*wbTL-pm*i@BK<37u*@m^2C`&P$F;N$IE{@ z>dg)2z36CQ_p{ZB&$AhdN>U-jZmIesdoonOG>A>EqJSL5)*_^r^3doW@on1AH3Z%7 z1Fepvr2YFdxhmGe0#2`c!pj~)lZ3YoAWi*`X^TxO4*0N=_Bu^m3+$E_R3om%<%};j zZ$@I=9Xc^2SA?T_ustMmlp9v3UIrGgsc>OGCyB}LbE@}Gx~vfK19W%)>fC_f^+2Ve z`vs)m0K+vPCHG)$Kb;ZoF?GQ3Tp1f zsS({(N0Lcr30^#06KZ9i`rp1lO?3=BIDlw&PFrIByW+_A#!UHm|a-Erwn&<>5;F+Le zUR;Rz(E_Tz1OE0(k?db_CmuG&(cbHNTCntuEXW=n;w_GOs>7L*2RHso3j8pvut2fh zqTAsO)RJ7q=8}-ZKE|&v*Z6xjUNdXv+hj(eIUEGj$BA%(FKWsm^O5siX2Kz@{i$ya z?qv{4Y}L>NNk23}%w{6z$+>0ZCD2i~+@G8cUwlK=LOg{}-C|;~NSW+#G~_6AmmPpq zG~O{ufF%{1HpnwB%uv{pzkp>@5z~aCxB9Ssh zQ|{JJ5@~!o$28iVYjk&O_s&iAp*^+nX1OfZ%-}FU_iUGU6gwv(*iu(tv`Yag!ETC3 zbgK>NN_fC=^+o@yZ~zOaM>MeI5O}2t`9kz+Y2k6UAV~QsqNpzDEQ7aYNX`=tFIMV* z@MRfL&T<`dT{0Jg#YhgkM zWVldU?vtByb*Ba!B=(37quS|rRrW&w`h)|J6x+T_VHJ_af}=3?STIU4{vZWsy+~}e z~sH*ma z=|vclxD0Xhy+*{`cq%*e=A-8Ea}h z-kVC*$>thRyJPjuyrNz;1;+;an`p(DHV;F>1OVFM%aP!uQzV_zl6Kq7@UwptNaWin zNPs33)uN^m-ZI+C14v4HwG4A91(DGa-+%cIE$_FEm^`o_T2FuEl6a>KoomP$ftZw4 zCd}~^HDjA!i1oTJ@^ka#dn}xo@wmEyS0Mpg@f#8+PTk^J|RWuSD%^W>U%5A9uk{FK?!#_Ok6k;HuHYdqw0{! z|I*!Ju`Wj@=e(3hP{V|;@MY+Fs%Te_hHN!2{Z&rWu?0FWmhWy#n|6?5 z6~l0Dy@+~4UWJ#gJb{<>h;x%bwEsmNrI8$=7pz>gHyFvZdqac!T%!ZzC3w7SGB|P} zMG`BO2V-QZ_NqQCRTRvYDqkxo)!x6UMkpguY~=?R?Kt5@Kx3zE)RPUUz(gdR*^jt_ zPR;V<#wkPNGa@Fc%?N}K;TsDkVHPxG<719@BjG15Fq&ud;@JI_2kd(57{4$Z+&<|| zK0{+sN%&l2rE@$8MG4=)c*?xbGrq+6C)Apg|LR-UjgcHAt`L%N@flJP!f^x ziGt?Vwz##bLFjy8gG&N$9C%AF(xTY*32#Qz36Zl`JbLqYK-nyGHo=hh0)-6oueOCX z49D7vVtR$S-L0SYx6PVl{kGRwD40vc)2J_^fox0P8~`wK|BCY?&-j;YjsV<9Icrkz za*jCb#~ooy9(rNI5h=c|9BINnpY^+XAILmHXw7m^Ln`vd&1ZHZTtaKYT>s>qU6E}?q}lM^Tj ztSU{y3vWmZFOd62vnIzQyjPGh1qgYTm4SGDsx^|4VEB{fm+Z=97C!F6rKCE!f|dDt zf>q!QZ75p~gXG-2<1Q9Ao*kSFJq$>fuDAe$;FW*6;>Ns`1Nkb$HFcNu%k(nqOW2*I z(r$1WWKTI{PXbfh<6BYm{#@tk$1vBi7jJ%H*?pO%NN5L7@W}BphmDMv{k`4AFxIpj zW#}hMuzY`SvD_u~V-~mlDw9O59!xHFv9ka0_!oECO5?axbLtxUbUb=@ki?)@x`W%y zDc+i&4MU_6Hk|w;XJ%9q@}t0b%6wqhZ~uC|QgcYf6BC<`VcLO#YV_ol&&QZ}EJ5Ya zJvn^t<~`!4Mbqx)Oz|RMC_vRN;dQaO=9(;$7bXmSfu2hPb7+5(M&F1J2b-2*Wqa6M3iV}%7}eZJF?hK(EAvx`}3dK z_N{TBO-<<%;CK7FfJGxsiqeO_DkyV)OT_mu9BGQCP-%|bt|DRU>9P9(7r}h3@Qwej zVgIIX3+p3MM~fT*N7E=4>epQ5bX*UVnU>MqM#fMaRnk#ZBRK*m8Xx!>;c7Ce@kyNE zoeco}T@dG5NMjFw3T*!n6b|9+vxb`Oqjnkh78(GS7!h3?nED#U3|xgg0i2y+$_rqf z10yl;F~kywR6+m2H8*HkLnTW8v)X9SYtzZ-Tf>^3umZ{C>}|N5LYynp0~iLB7Usz4 z<<@u63_w`*&HFCYL4@?yCjod`jNQhQlxpD z>cDgz@VC82=WZ=-^MVg7z`nF@x}`%bZJAK18l+#Jk)t4 zwWPnXnK!q&{7oL@=AH=?b5W4@&SI-8XP>H+*10H92r6_%GF_R1mj&%9cpVbR@wjqp z9I%7WQ#@79iU2xnicJ?eRRi6IddZW`D8tq8UckBvS45vF&!2dY7w59Y=e6g3Ym;EO zEmyNv^O{1(V|a5N_89>23_xg%JKsz4$4H+sqaJY+f6~utE~IxF=d3pYBSZpt;Q4TadOZz2V?W?=gl%^q z3F=ax!R{~gn!%T4hknwd(g`&$h7rqIN&?1iG8X?sk@S=aMBz*H^!$O1ug@3=NAYXN zZ!g)qU`M*l>;gJlc@sB&5^GYz{*g4HD7t=beL>F?79TSl4u{tzO2zTG_ow+SAN!@u z@kCyJMq64Y;_BTFL-2+BU(Lw#Xd~xX6V95M?vSsH$B238ZYu?oso}gr;yQMZ(DhKp z$q$KApMeSSQI3)>rfN;qJtsP>g2F>ovy2fK!?s6E(Ulw^@e?0mT7-(7FGYXx_s=G& zK?#+KKQ~j~4-6CTzVlR;Art~{wME1hH+Rt3UgjObkGZ4o#>$64 zr;8jWX~)NUTKh-lL&G!GJVul(AK-ZwdWcFx?94fWD0}b)8|N+qMRpy85u@>mi5LUv zYul(cFfn)0Qmok;&Mm`-qS0jF02;}`SDD5HVJZKpcR z`=r=7MEx#zCT*Bc@>Bg5N}iuY+_2<;-5RBM+w{{72t(KmhzLmNnG+dYQRYwka0P1j~1 z@Jsj!$U9=r91q=SK^C$Draqe0=FkhnB5kiIJge=IfQkzO`&KW{K?9Hl(;%ugFy=qFM>=EP(;`B5}$NgfIQ5BDt@wJWWX>^Nx<3_ zigA7pVP0;SxWPdk`4X0R>gU1*ZCrt0ypxqe*{kDhfq4(0N)cPR=-l8&7;M(F^xAuX>V^-ffOb#b zF`uSOK==N}Ap-)cjcfSxdTB1Ll5bdla9mo;Tf)C#noFoiGlEp#*?Hy77&|#y7)L_Y z?yhl=X~!8J#GCz+T+$(LMkSiD)iHn|uE4xtDrcAtR^n95Xi5+wJqkRf$Y(d z>xcGz;k$;<6$b6`M?rC3x1lab0FjejLfGZ&4_7}2lK7EwIeRVaI({&YkFGD$1W@Sn z*@{@pdm0^Z5)eIn-Bi0N+Skna9D%{8#a!z|)hxJL;P0^dwkNDSy>Jkz@lQOHn z+FubGOu6uO--sXp>RKPcUSl|p{P*CkeMikjP8-2pDfNHuVzw46Lh!b{oPM%lN0%Q~ zK=sB0`rXxS{8%2C2P5?>!Lcrrjc^ttfMjbO}cMX|5mm>NzvPz?= zMhbLH%if1BJXCWnCOc;kC?;BsL07DIFM?K7JmPWb{T0?LiJRDo8@`8As`ZLsL{flt zt4>bYPC#dQK;i9Kst}vBXxv7))WQ=@BdEwCzEUH3IOAAv0s<%`f`iu4(41%mSQ-Hn z3JjxlvF?I3UA3LPDAHPEifTWRw((xhYLj`3!g*;Gk_sX3zm!h^js936ntTk=A}0SS z$46=Y8(+vRVUhKlxo@F2mG31k@y1(J*xPSWhIO=gO9yl+j+0P9rhz@v!am@-jS`&>C3MGQkqSCHz;@|3Vp% z#xG=o-XH_7;IGACvEWJbG?2k)whd@dmk|ALACpb2jC5b_5fEz8Y1f_V z-TsKZpi!{dxK~`ej7T(7sCDkc*QmmY3 zPscyq$~;od`Oax3hF3C1M@YhxNmpln$aNF9Uof&|*$j7&jDj%jFO*=QP;}s_I-PD* zxB1ia(@sB2rqfTJcykx&k)TDKft|sxwV>aujm$`t3JPs#o}WiA{gb7`#8lD{!8!36 zrxtkG9c=e_Oex2&W+flRx18>`9VVo{d*UjmOQA6VrP2h9c}}snFlo*PpzTbPVrgDW z_ORBQmXGY`ruj2r4TL5!j7tQDdnS#t z<>b7Yia;q*sFWyFO6<6$p1;X)!i1sWAeySfoK=mp>UUvx{X_j4&&^A($y~K%?E6`? zuNox;i5ma7OK_I3O_YTbhxT|lBT|5Y{VsNt7}F}XEZ6_}>OM>bF0R$n=5K%I#p!tC1W`cUx^F@)#$C81osB?s*=tu&y zq1fPD(Dc5CGTajpy*ta!3QSK{EN1(IlX|EA4Zo_RDKM6~)DV)PzX%zxfZJMOaO=mS zn*ygIE17j+HE@g?H*Gv1>2C9s`Od_#`U%1R>hBe$Qh{*1veCz>sUNMBG!)Om;KRVD zEV)3CBb?|8gDb*7A|0-}!#;1Um?;R98H~C+P_pNz5mOhyJ7<0loTzPK+O^X|OE;BQ zPR>bTbQPAPA71#*L)c87=AuWy6ovPH+B@sGD7$vw58X&gr$d9JfJ#aZ-O?c)N{94- zA{|4A(k)0yH`3iDDJ3f1HD~at_j&fS-+lIHpZA;%XY<$1C==i7cin4U*ZQqBEvNRJ z@B(dq-LI0Fq_~_BQgVH}{c{NyTZ@o+HNR~$e|i+~2K>r+oacM$y&tVWp}cjGm}r## z?9f|8FUU`x27eQOIGM|k^u;=?D+9+n4lbw-gdiTjdl?xQIkpS!|wr8Ks0 zICSdGA~bMPJm=qgVf?!8)f<$8UT^qfqMUIzZfOULSdxEH@4;Ea`b3*(Gfq~i zF#;9itLK3B=X<(6No;oSDuU?fTV+0G?^Ez(OJeK{zBZsUKg6aSY_A%4J{)Q32k&Pn z^8RiC@`Jbz2Cc53P?2TD-G{SZCCb9P&f9TOm`ek-HSSFMd=PqnU-*mgsD+W~+2kuj zKIK}^yA`;HqGXpWi~%dYL3d}&sT++qFS8+|F?UxVzCs7f$LLp)vZxukv;p+M$hxKh zjFaE8u>!`nXXVWGy24L%pA2JS4ph{QI=$J-3~9i3w@7yqi7(Eecsk6!O)Aw-zYk(rr=-bwPcPplRo<+Q3G*g><}Ys3H07=Z}FU$0BK; zX^AqO2(G##vheh7#^8lR;yc#hr3I$g6EUv}DSGejF1{1e%Yd@y zYC)X4I$20TsOFA)wWAE*UmL}V>}B4I9{A|l= zoGEVvu+ZWsuo8V1iiTV_v^T%3UZ!%-~NXL|fSkn)Sx<;h*tTS$jUobLKQ< z?D4j~@7R!dH?a4^x7OWLvV_ShfX`tgwrT3Ss!{5Y2Qwv++y3kp;;to>4))D3zb4_y z1*jaqaY#)-5QpzuM&4A}L7oo}vdzL68kQ64hL<=&P#s&YJl)*-?DPu2Y$kV1aUO;+c4)9AVE@0gzqINGMM|6r18`xr88UmK+Qo zCkg$|XO=jfb6ELofeTjx9R(7SUZg2Y$#CVkOjy<;3>3}0FI>Is@9VJ@&d<~+@`60m zWbH-qW~8x(TmJS$KiNb5(Do*?zCmP=nLs!;*i+c-Be2bc*Vbq(4gsm!-q;7TvqRma z+P?Zklxjm!n23xJ;bc08Wg%~e=xcog;iTmf+oN^e{^#ThcIy;*+96yfi&gWU-$7R* zI?u0Uh1cncOXTbfR+maRI_?SSwsb8kBHg@Rc z`jOAs!2_2;=$D0ynmiw9_S`5GT2#Oag&r=mZbL8iq3LzdeBn*oxvxIPv0`Y)bBQ$r zL24mNu>ThFdf_8Y&ee)ARFKD~?b{V~lk&zZAql>cz^dFnRMn~aE$V8$jfX0&dktz+ z42MNO{Cu?Mrzkl^^K7Ff1p78-!jEVbFicd!<@~BD(Jsvo_=<#O=*wSSk}1!ZC^Ub= zXh31s{n$nnmbYz;S65j-gs;54D3+vG-F@C7T$B2VsQ@j<%%%uBW$^ML^U`8q5F7;b zF^@j|xE8oNv+2H4oc?SI&<$sQr;Kc898CSiz$f&Ki5}~nJw&bvZWdJIq1J?_#hPzi`N zig-OT>Zlgeet>uK}Z3N;{tMaH9Rz8joemz6&|hCQvMjp$0uq5DePhjseQ;f`M( z{0_WC^pFDj459w|var9`0D8sNs6OJY{p}+b8s%Cd3)wQ`koo1iCRa0us{Q^1lb31A zY31a?EoTlNo_$gM`O9yg(-#n0GH*XITRGAu_ll{B#j5V{BRYlD$mofaXKwJw%S~mc zQ>xaYdL;)~WvMX(9UnezmVJ`xxgz6e5Hz$ks;@M`MSnHfGHCl0RX z<*nq2#$vV2ltPpUC%v*rh*tA#w_WXKJt2QY4;-iB)H(SQdW6uNLHgRLpFM8c`>=D$ zEgnyqW{KXMSn&YJhC(o0ZueuCdSUcro>wgS&Un0uaQhMc2N$a-Vp=-|E;I9<)FmU& z9T|bA(`tyUiWU^DCUQ@4k}%~*^mIF>u=2ozGoRD^Md6E8N(|P035DJ3q2c zn&Gh3Ysp)4dS`rP`9V5;5`q zq+J`bBxhWLy*4C(#fw0UamBajcWye{!cNk&jDX=rFjLG(L*SH)6&i@Fs^Xz_gcV@H zAiRowfge1DBS~l@nyuS4UoH#GCq&$)<;p-n*pM0Ee0pcPOEI}ta!P;;X9<@9wT=_3 z2|2fq=rupq=$;jO0VQ%(Cy9Fr%5=yhs%irWEqRet`)-h1A}PUxL?gqV?t^*@#u8|5 z**(!}j9Bc=h_RN}c)l8`hUTU`UE{giI*41f-pZ{^tY0>yr?}jvJbTDLFR58czI8N{ zy*$BqQZMhd(*GbP-Owlw9WVN0vME6YoWQW5Pk-H|wS|7m61an9W~;NIlO%Vr*}4BD z=UyXQl7CsCg47t*BcZj6Je7>7OmBfEER{+Rm14<}yC&E)exywtVQI;8oRn_;D6XWF z@?Y-^>_(v!I;xrmK5$FVR%6eW@TT0 z2=K3|*opa6wPR!5(f-l-@Qr%S9lJEz3w+jlUQrZvgHPkCUt33gR+!C~B=C^l5>R)w3Xf!1E;C?{@;SUtbbY;~eu6l~I#9<`rD&``?) z@z_V+=_GbI48j5EW!pRJ#v+koG&j-H3dQAlZ11P!JVTO(`XgRZ^Ui;+a+@$6nU?Vp zReUP2AnSTOy7chM{6M8~5~IuczWP#SgLy^4$Ni`f(_Pd19uXoT4gwM2?*bllvx(u6 zV5(!>oQjaI&+~hs2dp8w0{eKzlN6R{$JW$sgqDd)wt^T$?g+~s{HSR4wFMJvg24(Q zLQ$Olvs9iLOT{GeI?eWqX_YO~hza;)1k~L{o^R)3?2|U+e5DO>EQ7P3>A=r~y7xWe z))O+ngufq4W#<3xVXVdV3{oyZfGrK5}Ix!PDP)tZAEgbG`I^g{9RAt@D znkZ6XWN@+$YF@5I`i7isH*JYIp7I@YcP5#xXPo;&Doxn|6Ho*6&_GE_7INGmbT9h6 zL|r&|m$Ym@*)!O*aeCgseClirl!BieI?KjQo;xV}P0!Yl63+lRy;RY@?SZYs2P$0} zG2k)FtcconEmN?U#te&MeK?Djolci@qV|)401v0~?-acx_)!pYKcx%yHF0=gKo@|Me{~ zn?axEO`3OtK$-fR(BHj zv#<;3yi^`+205Mv1tL1eDft&tGlE|>iiq~{hl+^SIl2s)yZiD(_wg!v411G4$l=!2 z_4#SlT2J@)59rp^zSB_LTB&p#I6Ras4+vuc3O>zQyC6+moWnViePoaQ&;8V*5)p$uKOpZ#=z|kxI+<-M*@D zHQihOxJ$@d;v}Xxrd{7@pB&rsC{VPJ^PzVfD^EWG9dNYJX-4D%b}l{DF5{jnQmoI| za$WGeRmes?eJj|ww3+VQY?w+B+nLw<4EceaR=hLr$hk?-`rE$7l?#L>XA_zGtUC-u z)sOVj3%`t(dGTYe;Vy)`cOLCIN!_I;f={+$ohhf;PBpoDz{!~)9O3z88#Xz%{xoR& z0qAG|mIj<|somvr7{XUM;co`zY-uZ?=Seo&Ys(bJg@xRK3fQW?CV;?~=S% z5G0I)sB9oiE+USX}n7T*H`SvXRa2(cDbZrq6VaQsp2D4{U| z0YIi`Dj2W>7$*EF3gRHPRmNvulMSHF{DuY_fJ2)X^+9+*>5#xUEz{8_5EU62c8!30 z7CCgltQZI+=Cj6%ze}?ak4u(a*yD1BYz{<6su^;N8L(nlVH$b<9X1Rsm2)ui{Adrz zk`B1s_2HXDD&erK5&A~oG7Aq#mY+!WMFy|s#|hyv9!PwwZcHOVr7pTd2>f<_iTLzr zKZuFW763<>H7I0hIZ;?n*Zh9Ookej}g8?A2lA%9Ml`eh{kegyrcogWg`p|;Gs*0_l z*FdWNk_K65o3Y<6^FeFqBs#b5AD24s0o;fm-XgKSV6B{B5PV}{(RE~HAD%Q@p?qf& z(RvAgj;xI}CM|M?p8w*WI{K>q4mnu%eNU--CJBfBF)|=Tn;7BZA=+hsp#g7^=gh}_ zGcB94@MA}0qVH$p7Wj@QIfp13kT+ffyfpk@8!Ov31aW!QuFTI%s|YJL#Anf-`++mF z#U0QvN+ZMS^fLl2movUR`rNw>O`PCnT2tERDC7(c>V8+xfp`|u_s(7fz6KVdI4~SB zpp@X32m#1B*be~im3;c*u*gV!l4ULXnhxVcM^q?=TcL^vixCJU^Mb`ew9b%<^sx%R z>)c0rC;@gIo1(S(x(17Wl`kN8#5|R!;+y(3WKqLX zkTCaaA-=D~GM%2NA?kT6xR1Cuw}(7|a#s(@GZQquZ0Nil(0wQ|zZKVE*- z{Kvoqgqo1hvEXb(kE(z+KWQJ&3-_vhMI*pdK`h48y0}Mmf@d+3*6YJc+~z`#1}K|E zmw4a2(=NZX`ZFk2ll_HSGHWZGtfexFy$HRm#q<~`52Z$U@K0K{3+=qR1Eczt+h&PI zwUzkbH5vTubX){8KiRZB#)=^uCc%r@_s$stbl;j=r1?EA~(fw;G}X+&^vd*%&_ zaI_6&Ky*1)Vg^NabZxe+>c+>&+0MVble}#x3)w3120cTC0;G2npQKi zVn6Gi7?3_hOf2902SHBbr_7HzwZWoEYu*fb+1w);k^Cxg8CX~$1I#7$)jZ`In6MY_ zDDw&ye|}cPqJg2rMwrn%#^NWD%%aTW%bY0^%{TT|mwPa^0ww-fo0m3zZhZQ+u_={4 zW`djE)7(6%E8u_}x8g?N(Yv=>ZG^}6G$4sDFOoOS>^+H3=)R=x3J;k>PpqLq5f{&( z%i>|sD`In1dG&)D=%B-!``>Zhb|oknefC9maWU0=%T!f%)2F3o3=-Lp>llrc`_Y|5 zCr!h5bb21A9U9|?vfnR34>5eqydPLsdIG{%f9r`-NE~`($T#oFUSKfun5x?L10HpBGjp)1R0>%;`}3vb~{%RFgxi%t%uI$NTY zDy*=rZn(&eO+HBe%4!#+j*w=jS=8aH2VU4|QlD6fLu3>zjI~=a=E9 zXrw!>3f04lXKLl8OQ|5nqvUi!*|n{@>o^mkQz}>0jonP_4NRKtw`d<^L7fT@8eIVYhWV9_Q)t&@gVx$T7+7WBMk9W-8(By%R}qYyE8M5&WRBE*~=i@v0X8nk(EY0ri- z(Jo|UWYJo8R~71rpfFk9krtrx6HZ^FbnF@s&CNBP;8|>8jm;?Q^Thj;DPvw zW2VLH^Y*riRDI1N@n)#xF@eP`V@=ZEVe!0@zK$NHt{-%kH@t9 zbnOy7qy4EFk&gPC_1Og(GTHC%HAJm<(FFt*rK)sRqw=k&m+&sQ*x6LQ zJ(Xq^)xA9w@Z5hQ554wU4vnLu}HmDd~6jyCO+0xRNj=#h!ZTJu%tqFfLjOcQ$&lmcxt zTObfHt4?kRj-(g@0?`3uCS}x^8|)myB;R~{^R#auA*TG^vi+>HulGy1cw5$h()&}J zChpQWZ{W?cAYC9PYhtL+(his7&Nl{w&L10)n0_9iufopIfZ$mmHE_z9x;8L?@~h(a zcCz-7JQ`6FLy)S{hPb$x2 z@wRx!`Nfa6NmW%Q(f}13b^CT>E982NFL(-7hL!Dn{W}|<*NZba>r)D3EWx2fc+R>7 zDs0v(@n-@Td_{K{MstEG)?Vu3vWbgHsjwEWw{bo}Z^DdxkxeFDHrx0$LCv9suQL0s zPU;T^RIM{=%LMGZWk=Nu1ZDG&rCY3ATM2wwga$f`eEW`BJx+DQ;6@ku`yDzMaPLS> zF2==Y+~B@ zbu?`v=RvvN>sPUjo}WxSew;ZD{D|se%!8dAs`*ATu}_A%NhDL$7YvUIu>Un`L2S#5 zwMN1v2ykgVG_*kRApCB)D;$n3JXq8Unc-8s_F+8ffDoKM-`Mr!&+ESM2yNb1G$(PKsa_Cd)F&_0 zeZ4uakrIryE49dB-QX%jp^mB9{2mF(C6j|wW0Rq~e)Nj#u*K`C#B&UxFiTg#<&SJv z0D{35RVaL&NDk)-0fijF<1PDAv`+cMbOaJrs6TI=5I`Me7^?s&wSu|X88cOQ> zQgV4k7F#pQNJ{Zpizm!)fDkVbu$AShGK~E9$R-*!yieW01Ulr21jhx01Lq9Y3y|j% zd6=23aXI{C{=BcfF-#^C7z5G!AXVRBi3utPy`rVZsoH-!PY-YSa~^F*^OJv%57+Pf z7prBhii}c|O+OI-+w$gTrSoMCh_G^GA1_!Kwm#ed%d`8EWN_~~w?@MR%a)&)V^nA0MPO;qN z*NO9+Y})!p8Q7sx^mjLi4w`D_o+Iar%wVq)d`H&F=!#C`5~cf4vC)k%j~i|0VVgnr zgx~ISuZw8SQ7`UuE%la5Q{O6{TOKj|Y7{zhMyXxvF-sC;80-f^BqWnmFc?t)Nwhou7Dmw4jZ{8Ovd#YFI8YP);KpgO;Mr6B2!e)r-3M>KFPVZ&jH$x{-30qGM%L zi*v-j%XH362>DDBz7}H<$*cjx`(96rv2ii~v(w`1z~$Y9z}?!k8M+DdZ)MtCYyadX z(7&zPN1(n5^lz*75u|Sd{adSjyPH7&)@ncDCeXi~+V=$`H2+>JUl(da#164qE6sth zLQMj3NS>6ej2Q2_K09OMGMawL1cX39Oz$!>LTGcFCFE0Wy|%t^ae#8k39(RmnFB9Z zPOXAek938TbY1CoceFta@G7!eeer6_#HyY)+T!M&*5Z(KylKV3y9#+pHdqApki*(E ztF4coCl8zwWLE=G(6LRkATm#dg?JjK`q>$Do5sYTZy4COnDb)(EdNsF)p|Ji?+R?31XRi5SX5Ykuh3zKdbURxf^XXv?A? zfq0U+L;PUAE)}~VfYnd~-mgwMfw<5ae`VehO5(oQSeQ}yI#sfw?%l3-929_VzL*aM z>!qm@U!Y^>pi><4Prdq*b2bDH&G&znjFfcWIT7t5O>TKOOE-1rg{G7m?c81Qw{Q@| z&BUjY(rkQ~DFrHTow=x|{Z^PxI1AklgBdT{O6;f@Wm}lF$t-o?Ma4-? z^^g2{0}rk6@Bid)Halt@Fae66)TuEul zozP_eSudO!+_r!WY@KCqMZk;@kxOw^aW%U_}0(^)k-Nf4W}w0wcn{h5etj znf@nr{?(}ycoX>F($s+s9f&12f&VQYI;L&{|J$p7B-q!#|IhvZ|J~FHiSZ`zzpeUz z4MtJ|;1d3_K7C!ib?(5bw*a7cU=*#RPxtypmCALwpzrxalr{u*0V^ZYT!WVz&q+mE zY*e@srL-G7AX=yL4~kEM8rB$XF7KGUSEoGT3^{}@NCRV9K)|Lq7N5Nt7GBzfuBq(S z07vNPD8C{nF50QQM3Bm_o_kf`o-_EAzjfuwleg2lVWSsJic;AQum#n@ZqtDbmf^Rl zWn~+Gko~NAi8}86*JuN*- zlk^p8eDdBvu@wwHt1C19IUD|1bpEd`yU{+kjFif6vj*KkX5Va$LX5l<_<=sP!F~R< zh}kMr8Z%`(MG~(!o-KcCfW=Xna>D-NQwxF)VR-+1zu%mk71YMehEq8$W+89Qp7=20 z^H*3BFuuKQ~QesVkF1o5Sdi7?p^-{jm7imJ2Db4J!3BkdF0rJ*uVNX z*3Mw5fGa3^n5Hm)34ouhf#om+rT!lM;?aUQ?<>2dnz--&j>T*oHj%IZcz}_*ZbAV5 zH5u^#c;Q(T2aL1>h{A!52CT43+6rdKgcJB6wxT$HxxGjQFC9fILE$A|@B|I!T*3p& zmfzb-!B3pUq$j55LzHXNF?j)5o$t?eq2Ab{$yX7Nl7$za`s$Np1K~R9W#xn!XGjwn zz+M(NPY*@AYEd9#~iflq(euk77t-iPUe z+PcZpZm`~t2N;?7CJ6G+1=3%9D4xOorj3_>@RVD_)tP%PKdwwP+(4o-+d^^ zA~%8lKfN6or6w)TIBU5*`^zQ=m<#B|-}+E~bpid=hw_ID=vN=goK~j!68(NC>z{on zPam=1{U&qkNpzSCh|a`_WTxb&4<+dlR-cR2?>-b)m<#AHJ`|V>=ocT#we~G;0{vU7 z{m7d@|JG{1`XneH4zHK>yZiU-Kr=zqQ);y$SShr}p8& zD0u+;U(5fJa|C!K?=)0d)*~`s004l3#08X&qHD5M)_8VZ{!2&I1orb>>2N%bKA8{{ z534-CiZRGSD6t#diWvPa1C)+7pp|~88XHzW8*iue{JVG%Zn0h=I_1pPWf9c}gRGjc zfVIYLPv6$YC|aO@N1COgLEdqq+1j3uO+c^jpR4~zZ>%XD)^_+mJVabL<^MqY+wNrZ zh_KguRARN7rCpw@MB`%mrs3z}!=!O~YOpQeKX(_?;0=PqBO`Tj+nmh6Q0XDXFDQ+j zt7WEi&k;IYvDeNZ3Xja78*xsd1wdwyX_)&&#f&~BB4dBB%PcoZZ``_)~wtoGq zl_uwjh7w;;`&5Dehb2*H+nOkZd5I2mX7m->q%II|Mnk$ax>R)bMyPt|YH_Z|YKZoI zaMQV>Tam1fFEXew=t8ANmKo=7`+r_EHYlHdVD$$`7z;0BZBLKCy21eNeqs^0(>t1; z@Af*3M7^(mI&NB@drq)w=qmcI`_6}f?p;ETU+ACQ1p5E%2Jj*6Q#^`>{@?HW`PE4F zJAIMkX(A1AUq*>lO8f&-T#{@0ai4zxf7164{+0f|HjMt+EAiw3j`SqK!7ZC!HjbXD z^}lO>8`)J^OiWbH1&C=1uaLZmBop6!IrbZU-@Pm^5)HZL>9q8q0o=rAmj&jwA6b$1 z82jdNVDx9fsMLU6LI6B$w<7r+Aj05KH!J+(=y_}sZ#zNV&-*lTPE6siUkdqI44I0m zAtFi#;nFhBNSw#z)LyR=$$;v~bBjV3ajnpK?5Xj~pSi2lZ2U;>w`Q0Am-_l(si5js z)fx2hvXL+^{_^mQeKHq%bli7EF+L7GH}`}>*Hj!@kJ%gZ^Uq!q-C1DTG=iS@r5un7 zUlKfquFVo&HN>1Q9~ZqCenlQy$ec;ElXqxoRlj+r`yQH*wQNF)Ybh_Q?Tg6hb{}sh zo%@?~@Za2vemd2pI{Tziy1##ojE%usws)bwgGnm!h2u2RB)A%+;+^2`vpudzHytQh zS8-zPojzF1BV5hrkW_(MNc-Vx^p`C~5UXV$f?}1PS42Y{UWX=--03n;!{hPlpB){2 z18E(&-N#~%Mp2rBC;lEs&PKw1-2(RLg9v*E8&>)>#**re?7XIxPeYFtpC1TkwZE%p z*)Q{ykb_0n2aGCxomidYX~-o&U-$b+Ftr*!&sJh7sy0aEmW4R9%9V(IpK~Ss9P}8qVuI zC;A`Gz`x$)`tQ_+L{E>>urQK+TK+Ca?eRUNkXD3%b}s_$3=1_Bx=`>=_Js??)pBRz zQnX#y!pH8#>Vua>8WIMVPiW=WiIw^(*N=Hk;}T459RGG>SG7)swYAQRHk$WTdze+y zSQ*X&n{La5?@(614mH125ehA&H?$d2`m~PPSL!{^T{RO2e@b9xiwcW?I~djOpGE+5 zjXmiz#`IMf_V>d>BWcBlC(de!FD36 zgOwibC&6~9!W`A~I}YzExqT&yzwva@PQi0huf&TMgjcT3Z;KUT*^cJEanVYQ$2v9g zu!TS@V0LJ?4NE6x^G)5Puii&B%S?1EXvOw;bq?_YP2Uh+6$FNVHU z7X7(+;tobny9w}btMa>U0{q)`-~U7TJ2wITZB#z2&c`7BZ&>G_f3@s~`91eBEN%k){~-5o*t*W|^F55n zn*jf|D!=+Bz`w1^U%UzMZ=v$ZRqL#?>mtg*fU4kQFx;*mT;2{Cp$<~+M*ye_y?(?W Mt^jw(4~hMM0XqCOkpKVy diff --git a/src/main/frontend/playwright-report/data/8c72b585fa3d6ad6b85b44878d2427a335bdf9de.md b/src/main/frontend/playwright-report/data/8c72b585fa3d6ad6b85b44878d2427a335bdf9de.md deleted file mode 100644 index e3e09aae..00000000 --- a/src/main/frontend/playwright-report/data/8c72b585fa3d6ad6b85b44878d2427a335bdf9de.md +++ /dev/null @@ -1,432 +0,0 @@ -# Instructions - -- Following Playwright test failed. -- Explain why, be concise, respect Playwright best practices. -- Provide a snippet of code with the fix, if possible. - -# Test info - -- Name: search.spec.ts >> Global search >> keyboard navigation in search results (ArrowDown / Enter) -- Location: tests/e2e/search.spec.ts:106:3 - -# Error details - -``` -Error: expect(page).toHaveURL(expected) failed - -Expected pattern: /\/explorer|\/graph/ -Received string: "http://localhost:8080/" -Timeout: 5000ms - -Call log: - - Expect "toHaveURL" with timeout 5000ms - 8 × unexpected value "http://localhost:8080/" - -``` - -# Page snapshot - -```yaml -- generic [ref=e3]: - - complementary "Main navigation" [ref=e4]: - - generic [ref=e5]: - - generic [ref=e6]: - - img [ref=e7] - - generic [ref=e10]: IQ - - generic [ref=e11]: - - heading "Code IQ" [level=1] [ref=e12] - - paragraph [ref=e13]: Knowledge Graph - - button "Collapse sidebar" [ref=e14] [cursor=pointer]: - - img - - navigation [ref=e15]: - - link "Dashboard" [ref=e16] [cursor=pointer]: - - /url: / - - img [ref=e17] - - generic [ref=e22]: Dashboard - - link "Code Graph" [ref=e23] [cursor=pointer]: - - /url: /graph - - img [ref=e24] - - generic [ref=e29]: Code Graph - - link "Explorer" [ref=e30] [cursor=pointer]: - - /url: /explorer - - img [ref=e31] - - generic [ref=e35]: Explorer - - link "Console" [ref=e36] [cursor=pointer]: - - /url: /console - - img [ref=e37] - - generic [ref=e39]: Console - - link "API Docs" [ref=e40] [cursor=pointer]: - - /url: /api-docs - - img [ref=e41] - - generic [ref=e43]: API Docs - - generic [ref=e45]: - - generic [ref=e47]: - - paragraph [ref=e48]: Project Files - - generic [ref=e49]: 401 files - - generic [ref=e53]: - - img [ref=e54] - - textbox "Filter files" [ref=e57]: - - /placeholder: Filter files… - - tree "Project file tree" [ref=e58]: - - treeitem "Project 401" [expanded] [ref=e59] [cursor=pointer]: - - img [ref=e61] - - img [ref=e64] - - generic [ref=e66]: Project - - generic "401 graph nodes" [ref=e67]: "401" - - treeitem ".claude 3" [ref=e68] [cursor=pointer]: - - img [ref=e70] - - img [ref=e73] - - generic [ref=e75]: .claude - - generic "3 graph nodes" [ref=e76]: "3" - - treeitem ".github 31" [ref=e77] [cursor=pointer]: - - img [ref=e79] - - img [ref=e82] - - generic [ref=e84]: .github - - generic "31 graph nodes" [ref=e85]: "31" - - treeitem "pytest-of-dev 1" [ref=e86] [cursor=pointer]: - - img [ref=e88] - - img [ref=e91] - - generic [ref=e93]: pytest-of-dev - - generic "1 graph node" [ref=e94]: "1" - - treeitem "src 1.4k" [ref=e95] [cursor=pointer]: - - img [ref=e97] - - img [ref=e100] - - generic [ref=e102]: src - - generic "1439 graph nodes" [ref=e103]: 1.4k - - treeitem ". 1" [ref=e104] [cursor=pointer]: - - img [ref=e107] - - generic [ref=e110]: . - - generic "1 graph node" [ref=e111]: "1" - - treeitem "CLAUDE.md 43" [ref=e112] [cursor=pointer]: - - img [ref=e115] - - generic [ref=e118]: CLAUDE.md - - generic "43 graph nodes" [ref=e119]: "43" - - treeitem "README.md 53" [ref=e120] [cursor=pointer]: - - img [ref=e123] - - generic [ref=e126]: README.md - - generic "53 graph nodes" [ref=e127]: "53" - - treeitem "pom.xml 1" [ref=e128] [cursor=pointer]: - - img [ref=e131] - - generic [ref=e134]: pom.xml - - generic "1 graph node" [ref=e135]: "1" - - treeitem "sonar-project.properties 9" [ref=e136] [cursor=pointer]: - - img [ref=e139] - - generic [ref=e142]: sonar-project.properties - - generic "9 graph nodes" [ref=e143]: "9" - - generic [ref=e144]: - - banner [ref=e145]: - - generic [ref=e147]: - - generic [ref=e148]: - - img [ref=e149] - - searchbox "Search nodes, kinds, files..." [active] [ref=e152]: User - - button "Clear search" [ref=e153] [cursor=pointer]: - - img [ref=e154] - - listbox [ref=e157]: - - option "class UserService" [ref=e158] [cursor=pointer]: - - generic [ref=e159]: class - - generic [ref=e160]: UserService - - option "method findById" [ref=e161] [cursor=pointer]: - - generic [ref=e162]: method - - generic [ref=e163]: findById - - 'option "endpoint GET /users/{id}" [ref=e164] [cursor=pointer]': - - generic [ref=e165]: endpoint - - generic [ref=e166]: "GET /users/{id}" - - generic [ref=e167]: - - button "Toggle theme" [ref=e168] [cursor=pointer]: - - img - - generic [ref=e169]: Toggle theme - - button "User profile" [ref=e170] [cursor=pointer]: - - img - - main [ref=e174]: - - generic [ref=e175]: - - generic [ref=e176]: - - generic [ref=e177]: - - heading "Dashboard" [level=1] [ref=e178] - - paragraph [ref=e179]: Code knowledge graph overview - - button "Refresh stats" [ref=e180] [cursor=pointer]: - - img - - generic [ref=e181]: - - button "View Nodes in Explorer" [ref=e182] [cursor=pointer]: - - generic [ref=e185]: - - generic [ref=e186]: - - paragraph [ref=e187]: Nodes - - paragraph [ref=e188]: "0" - - paragraph [ref=e189]: Total graph nodes - - img [ref=e191] - - generic [ref=e197]: - - generic [ref=e198]: - - paragraph [ref=e199]: Edges - - paragraph [ref=e200]: "0" - - paragraph [ref=e201]: Relationships - - img [ref=e203] - - button "View Files in Explorer" [ref=e207] [cursor=pointer]: - - generic [ref=e210]: - - generic [ref=e211]: - - paragraph [ref=e212]: Files - - paragraph [ref=e213]: "0" - - paragraph [ref=e214]: Source files scanned - - img [ref=e216] - - generic [ref=e224]: - - generic [ref=e225]: - - paragraph [ref=e226]: Languages - - paragraph [ref=e227]: "0" - - paragraph [ref=e228]: Detected languages - - img [ref=e230] - - generic [ref=e235]: - - heading "Node Kinds" [level=3] [ref=e237]: - - img [ref=e238] - - text: Node Kinds - - list [ref=e241]: - - button "method 671 0" [ref=e242] [cursor=pointer]: - - generic [ref=e243]: - - generic [ref=e244]: method - - generic [ref=e245]: "671" - - progressbar [ref=e246] - - button "class 421 0" [ref=e247] [cursor=pointer]: - - generic [ref=e248]: - - generic [ref=e249]: class - - generic [ref=e250]: "421" - - progressbar [ref=e251] - - button "config_key 166 0" [ref=e252] [cursor=pointer]: - - generic [ref=e253]: - - generic [ref=e254]: config_key - - generic [ref=e255]: "166" - - progressbar [ref=e256] - - button "endpoint 74 0" [ref=e257] [cursor=pointer]: - - generic [ref=e258]: - - generic [ref=e259]: endpoint - - generic [ref=e260]: "74" - - progressbar [ref=e261] - - button "module 56 0" [ref=e262] [cursor=pointer]: - - generic [ref=e263]: - - generic [ref=e264]: module - - generic [ref=e265]: "56" - - progressbar [ref=e266] - - button "interface 54 0" [ref=e267] [cursor=pointer]: - - generic [ref=e268]: - - generic [ref=e269]: interface - - generic [ref=e270]: "54" - - progressbar [ref=e271] - - button "middleware 32 0" [ref=e272] [cursor=pointer]: - - generic [ref=e273]: - - generic [ref=e274]: middleware - - generic [ref=e275]: "32" - - progressbar [ref=e276] - - button "component 26 0" [ref=e277] [cursor=pointer]: - - generic [ref=e278]: - - generic [ref=e279]: component - - generic [ref=e280]: "26" - - progressbar [ref=e281] - - button "query 23 0" [ref=e282] [cursor=pointer]: - - generic [ref=e283]: - - generic [ref=e284]: query - - generic [ref=e285]: "23" - - progressbar [ref=e286] - - button "guard 19 0" [ref=e287] [cursor=pointer]: - - generic [ref=e288]: - - generic [ref=e289]: guard - - generic [ref=e290]: "19" - - progressbar [ref=e291] - - button "abstract_class 17 0" [ref=e292] [cursor=pointer]: - - generic [ref=e293]: - - generic [ref=e294]: abstract_class - - generic [ref=e295]: "17" - - progressbar [ref=e296] - - button "config_file 15 0" [ref=e297] [cursor=pointer]: - - generic [ref=e298]: - - generic [ref=e299]: config_file - - generic [ref=e300]: "15" - - progressbar [ref=e301] - - button "event 12 0" [ref=e302] [cursor=pointer]: - - generic [ref=e303]: - - generic [ref=e304]: event - - generic [ref=e305]: "12" - - progressbar [ref=e306] - - button "queue 10 0" [ref=e307] [cursor=pointer]: - - generic [ref=e308]: - - generic [ref=e309]: queue - - generic [ref=e310]: "10" - - progressbar [ref=e311] -``` - -# Test source - -```ts - 19 | await mockStats(page); - 20 | - 21 | // Mock search API - 22 | await page.route('**/api/search**', route => - 23 | route.fulfill({ - 24 | status: 200, - 25 | contentType: 'application/json', - 26 | body: JSON.stringify(MOCK_SEARCH_RESULTS), - 27 | }) - 28 | ); - 29 | }); - 30 | - 31 | test('search box is visible in header on all views', async ({ page }) => { - 32 | for (const route of Object.values(ROUTES)) { - 33 | await gotoRoute(page, route); - 34 | await expect(page.getByRole('searchbox')).toBeVisible(); - 35 | } - 36 | }); - 37 | - 38 | test('typing fewer than 2 characters does not trigger search', async ({ page }) => { - 39 | await gotoRoute(page, ROUTES.dashboard); - 40 | let searchCalled = false; - 41 | await page.route('**/api/search**', () => { searchCalled = true; }); - 42 | - 43 | await page.getByRole('searchbox').fill('U'); - 44 | await page.waitForTimeout(400); // debounce window - 45 | - 46 | expect(searchCalled).toBe(false); - 47 | }); - 48 | - 49 | test('typing 2+ characters triggers search with debounce', async ({ page }) => { - 50 | await gotoRoute(page, ROUTES.dashboard); - 51 | const searchBox = page.getByRole('searchbox'); - 52 | await searchBox.fill('User'); - 53 | - 54 | // Wait for debounce (300ms) + render - 55 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 56 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 57 | }); - 58 | - 59 | test('search results show correct names and kinds', async ({ page }) => { - 60 | await gotoRoute(page, ROUTES.dashboard); - 61 | await page.getByRole('searchbox').fill('User'); - 62 | - 63 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 64 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 65 | - 66 | await expect(dropdown.getByText('UserService')).toBeVisible(); - 67 | await expect(dropdown.getByText('findById')).toBeVisible(); - 68 | await expect(dropdown.getByText('GET /users/{id}')).toBeVisible(); - 69 | }); - 70 | - 71 | test('clicking a result navigates to the Explorer view', async ({ page }) => { - 72 | await gotoRoute(page, ROUTES.dashboard); - 73 | await page.getByRole('searchbox').fill('User'); - 74 | - 75 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 76 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 77 | await dropdown.getByText('UserService').click(); - 78 | - 79 | // Should navigate to explorer with the selected node - 80 | await expect(page).toHaveURL(/\/explorer/); - 81 | }); - 82 | - 83 | test('pressing Escape clears search dropdown', async ({ page }) => { - 84 | await gotoRoute(page, ROUTES.dashboard); - 85 | await page.getByRole('searchbox').fill('User'); - 86 | - 87 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 88 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 89 | - 90 | await page.keyboard.press('Escape'); - 91 | await expect(dropdown).not.toBeVisible(); - 92 | }); - 93 | - 94 | test('clicking outside search closes the dropdown', async ({ page }) => { - 95 | await gotoRoute(page, ROUTES.dashboard); - 96 | await page.getByRole('searchbox').fill('User'); - 97 | - 98 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 99 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 100 | - 101 | // Click somewhere outside the search bar - 102 | await page.locator('main').click({ position: { x: 10, y: 10 }, force: true }); - 103 | await expect(dropdown).not.toBeVisible(); - 104 | }); - 105 | - 106 | test('keyboard navigation in search results (ArrowDown / Enter)', async ({ page }) => { - 107 | await gotoRoute(page, ROUTES.dashboard); - 108 | const searchBox = page.getByRole('searchbox'); - 109 | await searchBox.fill('User'); - 110 | - 111 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 112 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 113 | - 114 | // Navigate with ArrowDown and select with Enter - 115 | await page.keyboard.press('ArrowDown'); - 116 | await page.keyboard.press('Enter'); - 117 | - 118 | // Should have navigated -> 119 | await expect(page).toHaveURL(/\/explorer|\/graph/); - | ^ Error: expect(page).toHaveURL(expected) failed - 120 | }); - 121 | - 122 | test('loading indicator shows while search is in progress', async ({ page }) => { - 123 | // Slow down the search response to see the loading state - 124 | await page.route('**/api/search**', async route => { - 125 | await new Promise(resolve => setTimeout(resolve, 300)); - 126 | await route.fulfill({ - 127 | status: 200, - 128 | contentType: 'application/json', - 129 | body: JSON.stringify(MOCK_SEARCH_RESULTS), - 130 | }); - 131 | }); - 132 | - 133 | await gotoRoute(page, ROUTES.dashboard); - 134 | await page.getByRole('searchbox').fill('User'); - 135 | - 136 | // Loading indicator should appear briefly - 137 | const spinner = page.locator('[data-testid="search-spinner"]'); - 138 | await expect(spinner).toBeVisible({ timeout: 500 }); - 139 | }); - 140 | - 141 | test('empty search results shows "no results" message', async ({ page }) => { - 142 | await page.route('**/api/search**', route => - 143 | route.fulfill({ status: 200, contentType: 'application/json', body: '[]' }) - 144 | ); - 145 | - 146 | await gotoRoute(page, ROUTES.dashboard); - 147 | await page.getByRole('searchbox').fill('xyznonexistent'); - 148 | - 149 | const dropdown = page.locator('[data-testid="search-dropdown"]'); - 150 | await expect(dropdown).toBeVisible({ timeout: 1000 }); - 151 | await expect(dropdown).toContainText(/no results/i); - 152 | }); - 153 | }); - 154 | - 155 | // ── File tree filtering (Phase 2 Frontend) ──────────────────────────────────── - 156 | - 157 | test.describe('File tree search integration', () => { - 158 | test.beforeEach(async ({ page }) => { - 159 | await mockStats(page); - 160 | await page.route('**/api/file-tree**', route => - 161 | route.fulfill({ - 162 | status: 200, - 163 | contentType: 'application/json', - 164 | body: JSON.stringify({ - 165 | name: 'root', - 166 | children: [ - 167 | { name: 'src', children: [ - 168 | { name: 'main', children: [ - 169 | { name: 'java', children: [ - 170 | { name: 'UserService.java', nodeCount: 5 }, - 171 | { name: 'UserController.java', nodeCount: 3 }, - 172 | ]}, - 173 | ]}, - 174 | ]}, - 175 | ], - 176 | }), - 177 | }) - 178 | ); - 179 | }); - 180 | - 181 | test('typing in search filters the file tree', async ({ page }) => { - 182 | await gotoRoute(page, ROUTES.explorer); - 183 | await page.getByRole('searchbox').fill('UserService'); - 184 | - 185 | // File tree should filter to show only matching files - 186 | const tree = page.locator('[data-testid="file-tree"]'); - 187 | if (await tree.isVisible()) { - 188 | await expect(tree.getByText('UserService.java')).toBeVisible(); - 189 | // Non-matching file should be hidden - 190 | await expect(tree.getByText('UserController.java')).not.toBeVisible(); - 191 | } - 192 | }); - 193 | }); - 194 | -``` \ No newline at end of file diff --git a/src/main/frontend/playwright-report/data/b2072c8aa5cd97f91093ec8cad3e5f7b48b55c66.md b/src/main/frontend/playwright-report/data/b2072c8aa5cd97f91093ec8cad3e5f7b48b55c66.md deleted file mode 100644 index eac5b650..00000000 --- a/src/main/frontend/playwright-report/data/b2072c8aa5cd97f91093ec8cad3e5f7b48b55c66.md +++ /dev/null @@ -1,222 +0,0 @@ -# Instructions - -- Following Playwright test failed. -- Explain why, be concise, respect Playwright best practices. -- Provide a snippet of code with the fix, if possible. - -# Test info - -- Name: search.spec.ts >> File tree search integration >> typing in search filters the file tree -- Location: tests/e2e/search.spec.ts:181:3 - -# Error details - -``` -Test timeout of 30000ms exceeded. -``` - -``` -TimeoutError: page.waitForSelector: Timeout 30000ms exceeded. -Call log: - - waiting for locator('main') to be visible - -``` - -# Page snapshot - -```yaml -- generic [ref=e3]: - - heading "Something went wrong" [level=1] [ref=e4] - - paragraph [ref=e5]: Cannot read properties of undefined (reading 'toLocaleString') - - button "Reload page" [ref=e6] [cursor=pointer] -``` - -# Test source - -```ts - 1 | /// - 2 | import { type Page, expect } from '@playwright/test'; - 3 | import { readFileSync, existsSync } from 'node:fs'; - 4 | import { resolve } from 'node:path'; - 5 | - 6 | // ── Route helpers ──────────────────────────────────────────────────────────── - 7 | - 8 | export const ROUTES = { - 9 | dashboard: '/', - 10 | graph: '/graph', - 11 | explorer: '/explorer', - 12 | console: '/console', - 13 | apiDocs: '/api-docs', - 14 | } as const; - 15 | - 16 | export type AppRoute = (typeof ROUTES)[keyof typeof ROUTES]; - 17 | - 18 | /** - 19 | * Intercept the HTML shell served by Spring Boot and replace it with the - 20 | * current on-disk version. The running JAR may contain a stale index.html - 21 | * (built before the last frontend rebuild), causing it to load an old - 22 | * JS bundle that crashes before React mounts. - 23 | * - 24 | * Bug: STALE_BUNDLE — tracked in RAN-80 (filed separately). - 25 | */ - 26 | export async function patchIndexHtml(page: Page) { - 27 | // process.cwd() is the frontend dir when running `npx playwright test` - 28 | const staticDir = resolve(process.cwd(), '../resources/static'); - 29 | const diskHtml = readFileSync(resolve(staticDir, 'index.html'), 'utf-8'); - 30 | - 31 | const CONTENT_TYPES: Record = { - 32 | '.js': 'application/javascript', - 33 | '.mjs': 'application/javascript', - 34 | '.css': 'text/css', - 35 | '.svg': 'image/svg+xml', - 36 | '.png': 'image/png', - 37 | '.ico': 'image/x-icon', - 38 | '.woff2': 'font/woff2', - 39 | '.woff': 'font/woff', - 40 | }; - 41 | - 42 | // Intercept the SPA shell route (all navigation routes return the same HTML) - 43 | await page.route('**/*', async (route) => { - 44 | const req = route.request(); - 45 | const url = req.url(); - 46 | - 47 | // Serve HTML shell from disk - 48 | if ( - 49 | req.resourceType() === 'document' && - 50 | !url.includes('/api/') && - 51 | !url.includes('/swagger') && - 52 | !url.includes('/v3/') - 53 | ) { - 54 | await route.fulfill({ status: 200, contentType: 'text/html', body: diskHtml }); - 55 | return; - 56 | } - 57 | - 58 | // Serve static assets from disk if available (fixes stale-JAR bundle mismatch) - 59 | const assetMatch = url.match(/\/assets\/([^?#]+)/); - 60 | if (assetMatch) { - 61 | const assetName = assetMatch[1]; - 62 | const diskPath = resolve(staticDir, 'assets', assetName); - 63 | const ext = assetName.includes('.') ? '.' + assetName.split('.').pop()! : ''; - 64 | if (existsSync(diskPath)) { - 65 | const body = readFileSync(diskPath); - 66 | await route.fulfill({ - 67 | status: 200, - 68 | contentType: CONTENT_TYPES[ext] ?? 'application/octet-stream', - 69 | body, - 70 | }); - 71 | return; - 72 | } - 73 | } - 74 | - 75 | await route.fallback(); - 76 | }); - 77 | } - 78 | - 79 | /** Navigate to a route and wait for the main content area to be visible. */ - 80 | export async function gotoRoute(page: Page, route: AppRoute) { - 81 | await patchIndexHtml(page); - 82 | await page.goto(route); - 83 | // Wait for React to hydrate (main rendered by Layout component) -> 84 | await page.waitForSelector('main', { state: 'visible', timeout: 30000 }); - | ^ TimeoutError: page.waitForSelector: Timeout 30000ms exceeded. - 85 | } - 86 | - 87 | // ── Theme helpers ──────────────────────────────────────────────────────────── - 88 | - 89 | /** Returns the current theme: 'dark' | 'light'. */ - 90 | export async function getTheme(page: Page): Promise<'dark' | 'light'> { - 91 | const cls = await page.locator('html').getAttribute('class') ?? ''; - 92 | return cls.includes('dark') ? 'dark' : 'light'; - 93 | } - 94 | - 95 | /** Click the theme toggle and wait for the class to flip. */ - 96 | export async function toggleTheme(page: Page) { - 97 | const before = await getTheme(page); - 98 | // Theme toggle button — uses aria-label or data-testid set by the component - 99 | await page.getByRole('button', { name: /toggle theme|switch theme|dark mode|light mode/i }).click(); - 100 | await expect(page.locator('html')).toHaveClass(before === 'dark' ? /light/ : /dark/, { timeout: 2000 }); - 101 | } - 102 | - 103 | // ── API mock helpers ───────────────────────────────────────────────────────── - 104 | - 105 | /** Seed the `/api/stats` mock for deterministic dashboard tests. */ - 106 | export async function mockStats(page: Page, nodeCount = 1234, edgeCount = 5678) { - 107 | await page.route('**/api/stats', route => - 108 | route.fulfill({ - 109 | status: 200, - 110 | contentType: 'application/json', - 111 | body: JSON.stringify({ - 112 | totalNodes: nodeCount, - 113 | totalEdges: edgeCount, - 114 | nodesByKind: { endpoint: 10, class: 20, method: 30 }, - 115 | edgesByKind: { calls: 100, depends_on: 50 }, - 116 | languages: { java: 500, typescript: 200 }, - 117 | frameworks: { spring_boot: 300 }, - 118 | layers: { backend: 600, frontend: 200, infra: 100, shared: 50, unknown: 284 }, - 119 | }), - 120 | }) - 121 | ); - 122 | } - 123 | - 124 | /** - 125 | * Generate a synthetic node list for performance/stress tests. - 126 | * Returns a NodesListResponse-shaped object. - 127 | */ - 128 | export function generateNodeList(count: number) { - 129 | const nodes = Array.from({ length: count }, (_, i) => ({ - 130 | id: `node:file${i % 100}.ts:class:Class${i}`, - 131 | kind: ['class', 'method', 'endpoint', 'entity', 'function'][i % 5], - 132 | name: `Symbol${i}`, - 133 | qualifiedName: `com.example.Symbol${i}`, - 134 | filePath: `src/file${i % 100}.ts`, - 135 | layer: 'backend', - 136 | framework: null, - 137 | properties: {}, - 138 | })); - 139 | return { nodes, total: count, offset: 0, limit: count }; - 140 | } - 141 | - 142 | /** Seed the `/api/kinds` + `/api/nodes` endpoints with synthetic data. */ - 143 | export async function mockGraphData(page: Page, nodeCount: number) { - 144 | const data = generateNodeList(nodeCount); - 145 | - 146 | await page.route('**/api/kinds', route => - 147 | route.fulfill({ - 148 | status: 200, - 149 | contentType: 'application/json', - 150 | body: JSON.stringify({ - 151 | kinds: [ - 152 | { kind: 'class', count: Math.floor(nodeCount * 0.3) }, - 153 | { kind: 'method', count: Math.floor(nodeCount * 0.3) }, - 154 | { kind: 'endpoint', count: Math.floor(nodeCount * 0.15) }, - 155 | { kind: 'entity', count: Math.floor(nodeCount * 0.15) }, - 156 | { kind: 'function', count: Math.floor(nodeCount * 0.1) }, - 157 | ], - 158 | }), - 159 | }) - 160 | ); - 161 | - 162 | await page.route('**/api/nodes**', route => - 163 | route.fulfill({ - 164 | status: 200, - 165 | contentType: 'application/json', - 166 | body: JSON.stringify(data), - 167 | }) - 168 | ); - 169 | - 170 | await page.route('**/api/topology', route => - 171 | route.fulfill({ - 172 | status: 200, - 173 | contentType: 'application/json', - 174 | body: JSON.stringify({ - 175 | services: [ - 176 | { name: 'api-service', nodeCount: Math.floor(nodeCount / 3), dependencies: ['db-service'] }, - 177 | { name: 'db-service', nodeCount: Math.floor(nodeCount / 3), dependencies: [] }, - 178 | { name: 'frontend-service', nodeCount: Math.floor(nodeCount / 3), dependencies: ['api-service'] }, - 179 | ], - 180 | }), - 181 | }) - 182 | ); - 183 | } - 184 | -``` \ No newline at end of file diff --git a/src/main/frontend/playwright-report/data/f1d00512fbfc05f51c50987f6e805c0156f31b2d.png b/src/main/frontend/playwright-report/data/f1d00512fbfc05f51c50987f6e805c0156f31b2d.png deleted file mode 100644 index 2e81505d64fc7c0b441ffa32524daad0e728d1bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13387 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 AkpKVy diff --git a/src/main/frontend/playwright-report/data/f6eb10ff67df8fe6b39c93a7519699a0d4e67b55.webm b/src/main/frontend/playwright-report/data/f6eb10ff67df8fe6b39c93a7519699a0d4e67b55.webm deleted file mode 100644 index a092c5ee93de05d22c71780d75fef5b49a1f42d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234633 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 QdHiDx(d9lQ0CVeq0HLh+9{>OV diff --git a/src/main/frontend/playwright-report/index.html b/src/main/frontend/playwright-report/index.html deleted file mode 100644 index d3c4cd5f..00000000 --- a/src/main/frontend/playwright-report/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - Playwright Test Report - - - - -

- - - \ No newline at end of file diff --git a/src/main/frontend/playwright.config.ts b/src/main/frontend/playwright.config.ts deleted file mode 100644 index 1c5eb6dd..00000000 --- a/src/main/frontend/playwright.config.ts +++ /dev/null @@ -1,104 +0,0 @@ -/// -import { defineConfig, devices } from '@playwright/test'; - -/** - * Playwright E2E test configuration for codeiq UI Redesign (Phase 7). - * - * Prerequisites: - * - A pre-built CLI jar under ../../../target/code-iq-*-cli.jar - * (run `mvn -DskipTests package` from the repo root if missing). - * - A pre-populated fixture at /.seeds/spring-petclinic - * with .codeiq/cache + .codeiq/graph populated by - * `./scripts/baseline/run-pipeline.sh spring-petclinic`. The webServer - * block below boots `codeiq serve` against this fixture automatically. - * - Set `BASE_URL` / `E2E_FIXTURE` to override defaults when running against - * a different backend or fixture. - * - * Run all tests: npm run test:e2e - * Run headed: npm run test:e2e:headed - * Show HTML report: npm run test:e2e:report - */ -export default defineConfig({ - testDir: './tests/e2e', - // Use the test-specific tsconfig that includes @types/node - tsconfig: './tsconfig.test.json', - fullyParallel: true, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, - workers: process.env.CI ? 1 : undefined, - reporter: [['html', { outputFolder: 'playwright-report' }], ['line']], - - // Boot the real codeiq backend against a pre-enriched fixture before any - // spec runs. Skipped if BASE_URL points elsewhere (developer has their own - // backend) or if a server is already listening on the target port locally. - webServer: process.env.BASE_URL ? undefined : { - command: [ - 'bash -c', - // Use shell so the target/*-cli.jar glob expands. `exec` hands the PID - // to Playwright so it can kill the process cleanly on test teardown. - `"exec java -jar ../../../target/code-iq-*-cli.jar serve ` - + `${process.env.E2E_FIXTURE ?? '../../../.seeds/spring-petclinic'} ` - + `--port ${process.env.E2E_PORT ?? '8080'}"`, - ].join(' '), - // /actuator/health is not a reliable readiness signal today (see - // BASELINE.md §GraphHealthIndicator). /api/stats returns 200 iff the - // server has finished starting and the graph has loaded. - url: `http://localhost:${process.env.E2E_PORT ?? '8080'}/api/stats`, - timeout: 120_000, - reuseExistingServer: !process.env.CI, - stdout: 'pipe', - stderr: 'pipe', - }, - - use: { - baseURL: process.env.BASE_URL ?? `http://localhost:${process.env.E2E_PORT ?? '8080'}`, - trace: 'on-first-retry', - screenshot: 'only-on-failure', - video: 'retain-on-failure', - }, - - // Performance threshold constants (ms) shared via env so specs can read them - // Actual assertions live in performance.spec.ts - // PERF_THRESHOLD_100 = 500 - // PERF_THRESHOLD_1K = 2000 - // PERF_THRESHOLD_10K = 3000 - - projects: [ - // P0 — required for release sign-off - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, - - // P1 — run in CI when available - { - name: 'edge', - use: { ...devices['Desktop Edge'], channel: 'msedge' }, - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - - // Responsive breakpoints (chromium only — layout logic is shared) - { - name: 'desktop-1920', - use: { ...devices['Desktop Chrome'], viewport: { width: 1920, height: 1080 } }, - testMatch: '**/responsive.spec.ts', - }, - { - name: 'laptop-1440', - use: { ...devices['Desktop Chrome'], viewport: { width: 1440, height: 900 } }, - testMatch: '**/responsive.spec.ts', - }, - { - name: 'tablet-768', - use: { ...devices['Desktop Chrome'], viewport: { width: 768, height: 1024 } }, - testMatch: '**/responsive.spec.ts', - }, - ], -}); diff --git a/src/main/frontend/public/favicon.svg b/src/main/frontend/public/favicon.svg deleted file mode 100644 index 25da030c..00000000 --- a/src/main/frontend/public/favicon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - IQ - diff --git a/src/main/frontend/src/App.tsx b/src/main/frontend/src/App.tsx deleted file mode 100644 index 893b6e9b..00000000 --- a/src/main/frontend/src/App.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Routes, Route, Navigate } from 'react-router-dom'; -import AppLayout from './components/AppLayout'; -import Dashboard from './pages/Dashboard'; - -export default function App() { - return ( - - }> - } /> - } /> - - - ); -} diff --git a/src/main/frontend/src/components/AppLayout.tsx b/src/main/frontend/src/components/AppLayout.tsx deleted file mode 100644 index eda3718e..00000000 --- a/src/main/frontend/src/components/AppLayout.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { Outlet } from 'react-router-dom'; -import { useState } from 'react'; -import { AppShell, IconButton } from '@ossrandom/design-system'; -import { useTheme } from '@/context/ThemeContext'; - -function SunIcon() { - return ( - - ); -} - -function MoonIcon() { - return ( - - ); -} - -function CopyIcon({ ok }: { ok: boolean }) { - if (ok) { - return ( - - ); - } - return ( - - ); -} - -function McpUrlPill() { - const [copied, setCopied] = useState(false); - const url = (typeof window !== 'undefined' ? window.location.origin : '') + '/mcp'; - const onCopy = async () => { - try { - await navigator.clipboard.writeText(url); - setCopied(true); - setTimeout(() => setCopied(false), 1200); - } catch { - /* clipboard blocked — silent */ - } - }; - return ( -
- MCP · {url} - -
- ); -} - -function Header() { - const { isDark, toggle } = useTheme(); - return ( -
-
Code IQ
-
- - : } - aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'} - variant="ghost" - size="sm" - onClick={toggle} - /> -
-
- ); -} - -export default function AppLayout() { - return ( - }> -
- -
-
- ); -} diff --git a/src/main/frontend/src/components/Icons.tsx b/src/main/frontend/src/components/Icons.tsx deleted file mode 100644 index cbfdeab3..00000000 --- a/src/main/frontend/src/components/Icons.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { CSSProperties } from 'react'; - -const base: CSSProperties = { display: 'inline-block', verticalAlign: '-2px' }; - -function Svg({ d, size = 14 }: { d: string; size?: number }) { - return ( - - ); -} - -export const Icon = { - Nodes: () => , - Branches: () => , - File: () => , - Code: () => , - Api: () => , - Safety: () => , - Appstore: () => , - Build: () => , - Play: () => , - Clock: () => , - Search: () => , - History: () => , -}; diff --git a/src/main/frontend/src/context/ThemeContext.tsx b/src/main/frontend/src/context/ThemeContext.tsx deleted file mode 100644 index 9ef5e6f3..00000000 --- a/src/main/frontend/src/context/ThemeContext.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; - -type ThemeContextType = { isDark: boolean; toggle: () => void }; -const ThemeContext = createContext({ isDark: true, toggle: () => {} }); - -export function ThemeProvider({ children }: { children: ReactNode }) { - const [isDark, setIsDark] = useState(() => { - const stored = localStorage.getItem('theme'); - return stored ? stored === 'dark' : true; - }); - - useEffect(() => { - localStorage.setItem('theme', isDark ? 'dark' : 'light'); - document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light'); - }, [isDark]); - - return ( - setIsDark(d => !d) }}> - {children} - - ); -} - -export const useTheme = () => useContext(ThemeContext); diff --git a/src/main/frontend/src/env.d.ts b/src/main/frontend/src/env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/src/main/frontend/src/env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/src/main/frontend/src/hooks/useApi.ts b/src/main/frontend/src/hooks/useApi.ts deleted file mode 100644 index afa145b5..00000000 --- a/src/main/frontend/src/hooks/useApi.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useState, useEffect, useCallback } from 'react'; - -interface UseApiState { - data: T | null; - loading: boolean; - error: string | null; - refetch: () => void; -} - -export function useApi(fetcher: () => Promise, deps: unknown[] = []): UseApiState { - const [data, setData] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [trigger, setTrigger] = useState(0); - - const refetch = useCallback(() => setTrigger(t => t + 1), []); - - useEffect(() => { - let cancelled = false; - setLoading(true); - setError(null); - - fetcher() - .then(result => { - if (!cancelled) { - setData(result); - setLoading(false); - } - }) - .catch(err => { - if (!cancelled) { - setError(err instanceof Error ? err.message : String(err)); - setLoading(false); - } - }); - - return () => { cancelled = true; }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [trigger, JSON.stringify(deps)]); - - return { data, loading, error, refetch }; -} diff --git a/src/main/frontend/src/index.css b/src/main/frontend/src/index.css deleted file mode 100644 index 39d1a1b3..00000000 --- a/src/main/frontend/src/index.css +++ /dev/null @@ -1,134 +0,0 @@ -body { - margin: 0; - padding: 0; -} - -/* Layout-only — visuals come from design-system tokens. */ -.codeiq-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 0 16px; - height: 56px; -} - -.codeiq-brand { - color: var(--accent); - font-size: var(--fs-h4); - font-weight: var(--fw-semibold); - letter-spacing: -0.01em; - white-space: nowrap; -} - -.codeiq-content { - padding: 16px; -} - -.codeiq-header-actions { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; -} - -.codeiq-mcp-url { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 8px; - border: 1px solid var(--border-1); - border-radius: 6px; - background: var(--bg-2); - color: var(--fg-2); - font-family: var(--font-mono); - font-size: 12px; - max-width: 360px; - overflow: hidden; -} - -.codeiq-mcp-url > span { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.codeiq-mcp-url > button { - flex: none; - background: transparent; - border: 0; - padding: 2px; - color: var(--fg-3); - cursor: pointer; - border-radius: 4px; -} - -.codeiq-mcp-url > button:hover { - color: var(--fg-1); - background: var(--bg-3); -} - -/* Stats grid — auto-fit so cards flow on mobile. */ -.codeiq-stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); - gap: 8px; -} - -/* Hide the design-system Treemap's engine badge (renders "canvas"/"webgl" - in a corner — debug affordance, not desired in app chrome). */ -.rcs-treemap-engine-badge { - display: none !important; -} - -.codeiq-breadcrumb { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 4px; - padding: 6px 10px; - border: 1px solid var(--border-1); - border-radius: 6px; - background: var(--bg-1); - font-size: 12px; - color: var(--fg-2); - font-family: var(--font-mono); -} - -.codeiq-breadcrumb button { - background: transparent; - border: 0; - padding: 2px 6px; - border-radius: 4px; - color: inherit; - font-family: inherit; - font-size: inherit; - cursor: pointer; -} - -.codeiq-breadcrumb button:hover:not(:disabled) { - background: var(--bg-3); - color: var(--fg-1); -} - -.codeiq-breadcrumb button:disabled { - cursor: default; - opacity: 0.7; -} - -.codeiq-breadcrumb-sep { - opacity: 0.4; - user-select: none; -} - -@media (max-width: 600px) { - .codeiq-header { - padding: 0 12px; - } - .codeiq-content { - padding: 12px; - } - .codeiq-mcp-url { - display: none; - } -} diff --git a/src/main/frontend/src/lib/api.ts b/src/main/frontend/src/lib/api.ts deleted file mode 100644 index 2362fd33..00000000 --- a/src/main/frontend/src/lib/api.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { - StatsResponse, - KindsResponse, - NodesListResponse, - NodeResponse, - EdgesListResponse, - SearchResult, - FileTreeResponse, - TopologyResponse, - EgoGraphResponse, - NeighborsResponse, -} from '@/types/api'; - -const BASE = '/api'; - -async function fetchJson(url: string): Promise { - const res = await fetch(url); - if (!res.ok) { - const text = await res.text(); - throw new Error(`API error ${res.status}: ${text}`); - } - return res.json(); -} - - -export const api = { - getStats: () => fetchJson(`${BASE}/stats`), - - getDetailedStats: (category = 'all') => - fetchJson>(`${BASE}/stats/detailed?category=${category}`), - - getKinds: () => fetchJson(`${BASE}/kinds`), - - getNodesByKind: (kind: string, limit = 50, offset = 0) => - fetchJson(`${BASE}/kinds/${kind}?limit=${limit}&offset=${offset}`), - - getNodes: (kind?: string, module?: string, limit = 100, offset = 0) => { - const params = new URLSearchParams({ limit: String(limit), offset: String(offset) }); - if (kind) params.set('kind', kind); - if (module) params.set('module', module); - return fetchJson(`${BASE}/nodes?${params}`); - }, - - findNode: (q: string) => - fetchJson(`${BASE}/nodes/find?q=${encodeURIComponent(q)}`), - - getNodeDetail: (id: string) => - fetchJson(`${BASE}/nodes/${encodeURIComponent(id)}/detail`), - - getNodeNeighbors: (id: string, direction = 'both') => - fetchJson>(`${BASE}/nodes/${encodeURIComponent(id)}/neighbors?direction=${direction}`), - - getEdges: (kind?: string, limit = 100, offset = 0) => { - const params = new URLSearchParams({ limit: String(limit), offset: String(offset) }); - if (kind) params.set('kind', kind); - return fetchJson(`${BASE}/edges?${params}`); - }, - - search: (q: string, limit = 50) => - fetchJson(`${BASE}/search?q=${encodeURIComponent(q)}&limit=${limit}`), - - readFile: async (path: string, startLine?: number, endLine?: number) => { - const params = new URLSearchParams({ path }); - if (startLine !== undefined) params.set('startLine', String(startLine)); - if (endLine !== undefined) params.set('endLine', String(endLine)); - const r = await fetch(`${BASE}/file?${params}`); - if (!r.ok) throw new Error(`API error ${r.status}`); - return r.text(); - }, - - getCycles: (limit = 100) => - fetchJson>(`${BASE}/query/cycles?limit=${limit}`), - - getShortestPath: (source: string, target: string) => - fetchJson>(`${BASE}/query/shortest-path?source=${encodeURIComponent(source)}&target=${encodeURIComponent(target)}`), - - getConsumers: (id: string) => - fetchJson>(`${BASE}/query/consumers/${encodeURIComponent(id)}`), - - getProducers: (id: string) => - fetchJson>(`${BASE}/query/producers/${encodeURIComponent(id)}`), - - getCallers: (id: string) => - fetchJson>(`${BASE}/query/callers/${encodeURIComponent(id)}`), - - getDependencies: (id: string) => - fetchJson>(`${BASE}/query/dependencies/${encodeURIComponent(id)}`), - - getDependents: (id: string) => - fetchJson>(`${BASE}/query/dependents/${encodeURIComponent(id)}`), - - findComponent: (file: string) => - fetchJson>(`${BASE}/triage/component?file=${encodeURIComponent(file)}`), - - traceImpact: (id: string, depth = 3) => - fetchJson>(`${BASE}/triage/impact/${encodeURIComponent(id)}?depth=${depth}`), - - getFileTree: (depth?: number, path?: string) => { - const qs = new URLSearchParams(); - if (depth !== undefined) qs.set('depth', String(depth)); - if (path !== undefined && path !== '') qs.set('path', path); - const suffix = qs.toString() ? `?${qs}` : ''; - return fetchJson(`${BASE}/file-tree${suffix}`); - }, - - getTopology: () => - fetchJson(`${BASE}/topology`), - - getEgoGraph: (center: string, radius = 2) => - fetchJson(`${BASE}/ego/${encodeURIComponent(center)}?radius=${radius}`), - - getNodeNeighborsTyped: (id: string) => - fetchJson(`${BASE}/nodes/${encodeURIComponent(id)}/neighbors`), -}; diff --git a/src/main/frontend/src/lib/mcp-tools.ts b/src/main/frontend/src/lib/mcp-tools.ts deleted file mode 100644 index ea19d52e..00000000 --- a/src/main/frontend/src/lib/mcp-tools.ts +++ /dev/null @@ -1,333 +0,0 @@ -export interface ToolParam { - name: string; - type: "string" | "number" | "boolean"; - description: string; - required?: boolean; - default?: string; - options?: string[]; -} - -export interface McpTool { - name: string; - description: string; - category: string; - params: ToolParam[]; - url: string | ((params: Record) => string); - method?: "GET" | "POST"; -} - -export const CATEGORIES = [ - { id: "stats", label: "Statistics" }, - { id: "query", label: "Graph Queries" }, - { id: "topology", label: "Service Topology" }, - { id: "flow", label: "Architecture Flow" }, - { id: "analysis", label: "Analysis" }, - { id: "security", label: "Security" }, - { id: "code", label: "Code" }, -] as const; - -export type CategoryId = (typeof CATEGORIES)[number]["id"]; - -export const TOOLS: McpTool[] = [ - // -- Statistics -- - { - name: "get_stats", - description: "Graph statistics -- node counts, edge counts, breakdown by kind and layer", - category: "stats", params: [], url: "/api/stats", - }, - { - name: "get_detailed_stats", - description: "Rich categorized statistics: frameworks, infra, connections, auth, architecture", - category: "stats", - params: [ - { name: "category", type: "string", description: "Category filter", - options: ["all", "graph", "languages", "frameworks", "infra", "connections", "auth", "architecture"], - default: "all" }, - ], - url: (p) => `/api/stats/detailed?category=${p.category || "all"}`, - }, - - // -- Graph Queries -- - { - name: "query_nodes", - description: "Query nodes with optional kind filter", - category: "query", - params: [ - { name: "kind", type: "string", description: "Node kind filter", - options: ["", "endpoint", "entity", "class", "method", "module", "guard", "config_key", "infra_resource", "component", "service"] }, - { name: "limit", type: "number", description: "Max results", default: "20" }, - ], - url: (p) => `/api/nodes?kind=${p.kind || ""}&limit=${p.limit || "20"}`, - }, - { - name: "query_edges", - description: "Query edges with optional kind filter", - category: "query", - params: [ - { name: "kind", type: "string", description: "Edge kind filter", - options: ["", "calls", "depends_on", "imports", "extends", "implements", "exposes", "produces", "consumes", "protects"] }, - { name: "limit", type: "number", description: "Max results", default: "20" }, - ], - url: (p) => `/api/edges?kind=${p.kind || ""}&limit=${p.limit || "20"}`, - }, - { - name: "list_kinds", - description: "List all node kinds with counts", - category: "query", params: [], url: "/api/kinds", - }, - { - name: "get_node_detail", - description: "Full detail for a specific node including properties and edges", - category: "query", - params: [{ name: "nodeId", type: "string", description: "Node ID", required: true }], - url: (p) => `/api/nodes/${encodeURIComponent(p.nodeId || "")}/detail`, - }, - { - name: "get_neighbors", - description: "Get neighbor nodes with optional direction filter", - category: "query", - params: [ - { name: "nodeId", type: "string", description: "Node ID", required: true }, - { name: "direction", type: "string", description: "Direction", - options: ["both", "in", "out"], default: "both" }, - ], - url: (p) => `/api/nodes/${encodeURIComponent(p.nodeId || "")}/neighbors?direction=${p.direction || "both"}`, - }, - { - name: "get_ego_graph", - description: "Ego subgraph -- all nodes within N hops of a center node", - category: "query", - params: [ - { name: "center", type: "string", description: "Center node ID", required: true }, - { name: "radius", type: "number", description: "Hop radius (1-10)", default: "2" }, - ], - url: (p) => `/api/ego/${encodeURIComponent(p.center || "")}?radius=${p.radius || "2"}`, - }, - { - name: "search_graph", - description: "Free-text search across node labels, IDs, and properties", - category: "query", - params: [ - { name: "q", type: "string", description: "Search query", required: true }, - { name: "limit", type: "number", description: "Max results", default: "20" }, - ], - url: (p) => `/api/search?q=${encodeURIComponent(p.q || "")}&limit=${p.limit || "20"}`, - }, - { - name: "find_cycles", - description: "Find circular dependency cycles in the graph", - category: "query", - params: [{ name: "limit", type: "number", description: "Max cycles", default: "10" }], - url: (p) => `/api/query/cycles?limit=${p.limit || "10"}`, - }, - { - name: "find_shortest_path", - description: "Shortest path between two nodes", - category: "query", - params: [ - { name: "source", type: "string", description: "Source node ID", required: true }, - { name: "target", type: "string", description: "Target node ID", required: true }, - ], - url: (p) => `/api/query/shortest-path?source=${encodeURIComponent(p.source || "")}&target=${encodeURIComponent(p.target || "")}`, - }, - { - name: "find_callers", - description: "Find all nodes that call a target node", - category: "query", - params: [{ name: "id", type: "string", description: "Target node ID", required: true }], - url: (p) => `/api/query/callers/${encodeURIComponent(p.id || "")}`, - }, - { - name: "find_dependencies", - description: "Find all nodes this node depends on (outgoing dependencies)", - category: "query", - params: [{ name: "id", type: "string", description: "Node ID", required: true }], - url: (p) => `/api/query/dependencies/${encodeURIComponent(p.id || "")}`, - }, - { - name: "find_dead_code", - description: "Find potentially dead code -- classes/methods with no incoming references", - category: "query", - params: [ - { name: "kind", type: "string", description: "Filter by kind", - options: ["", "class", "method", "interface"] }, - { name: "limit", type: "number", description: "Max results", default: "20" }, - ], - url: (p) => `/api/query/dead-code?kind=${p.kind || ""}&limit=${p.limit || "20"}`, - }, - - // -- Service Topology -- - { - name: "get_topology", - description: "Full service topology map -- services and their connections", - category: "topology", params: [], url: "/api/topology", - }, - { - name: "service_detail", - description: "Detailed view of a specific service", - category: "topology", - params: [{ name: "name", type: "string", description: "Service name", required: true }], - url: (p) => `/api/topology/services/${encodeURIComponent(p.name || "")}`, - }, - { - name: "service_dependencies", - description: "What a service depends on (DBs, queues, other services)", - category: "topology", - params: [{ name: "name", type: "string", description: "Service name", required: true }], - url: (p) => `/api/topology/services/${encodeURIComponent(p.name || "")}/deps`, - }, - { - name: "service_dependents", - description: "Services that depend on this service", - category: "topology", - params: [{ name: "name", type: "string", description: "Service name", required: true }], - url: (p) => `/api/topology/services/${encodeURIComponent(p.name || "")}/dependents`, - }, - { - name: "blast_radius", - description: "BFS blast radius -- all services affected if this node fails", - category: "topology", - params: [{ name: "nodeId", type: "string", description: "Node ID", required: true }], - url: (p) => `/api/topology/blast-radius/${encodeURIComponent(p.nodeId || "")}`, - }, - { - name: "find_path", - description: "Find shortest path between two services", - category: "topology", - params: [ - { name: "from", type: "string", description: "Source service name", required: true }, - { name: "to", type: "string", description: "Target service name", required: true }, - ], - url: (p) => `/api/topology/path?from=${encodeURIComponent(p.from || "")}&to=${encodeURIComponent(p.to || "")}`, - }, - { - name: "find_bottlenecks", - description: "Services with the most connections (potential bottlenecks)", - category: "topology", params: [], url: "/api/topology/bottlenecks", - }, - { - name: "find_circular_deps", - description: "Circular service-to-service dependency cycles", - category: "topology", params: [], url: "/api/topology/circular", - }, - { - name: "find_dead_services", - description: "Services with no incoming connections (potentially unused)", - category: "topology", params: [], url: "/api/topology/dead", - }, - - // -- Architecture Flow -- - { - name: "generate_flow", - description: "Generate architecture flow diagram for a specific view type", - category: "flow", - params: [ - { name: "view", type: "string", description: "View type", - options: ["overview", "ci", "deploy", "runtime", "auth"], default: "overview" }, - ], - url: (p) => `/api/flow/${p.view || "overview"}?format=json`, - }, - { - name: "list_flows", - description: "List available architecture flow view types", - category: "flow", params: [], url: "/api/flow", - }, - - // -- Analysis -- - { - name: "find_component_by_file", - description: "Find which component/layer a file belongs to", - category: "analysis", - params: [{ name: "file", type: "string", description: "File path (relative to codebase root)", required: true }], - url: (p) => `/api/triage/component?file=${encodeURIComponent(p.file || "")}`, - }, - { - name: "trace_impact", - description: "Trace downstream impact from a node", - category: "analysis", - params: [ - { name: "nodeId", type: "string", description: "Node ID", required: true }, - { name: "depth", type: "number", description: "Max depth", default: "3" }, - ], - url: (p) => `/api/triage/impact/${encodeURIComponent(p.nodeId || "")}?depth=${p.depth || "3"}`, - }, - { - name: "find_consumers", - description: "Find nodes that consume/listen to a target", - category: "analysis", - params: [{ name: "targetId", type: "string", description: "Target node ID", required: true }], - url: (p) => `/api/query/consumers/${encodeURIComponent(p.targetId || "")}`, - }, - { - name: "find_producers", - description: "Find nodes that produce/publish to a target", - category: "analysis", - params: [{ name: "targetId", type: "string", description: "Target node ID", required: true }], - url: (p) => `/api/query/producers/${encodeURIComponent(p.targetId || "")}`, - }, - { - name: "find_dependents", - description: "Find all nodes that depend on this node (incoming dependencies)", - category: "analysis", - params: [{ name: "id", type: "string", description: "Node ID", required: true }], - url: (p) => `/api/query/dependents/${encodeURIComponent(p.id || "")}`, - }, - { - name: "find_node", - description: "Find a node by name or qualified name", - category: "analysis", - params: [ - { name: "q", type: "string", description: "Node name or qualified name", required: true }, - { name: "kind", type: "string", description: "Optional kind filter", - options: ["", "class", "method", "endpoint", "entity", "component", "service"] }, - ], - url: (p) => `/api/search?q=${encodeURIComponent(p.q || "")}&kind=${p.kind || ""}&limit=10`, - }, - { - name: "find_related_endpoints", - description: "Find REST endpoints related to or calling a node", - category: "analysis", - params: [{ name: "nodeId", type: "string", description: "Node ID", required: true }], - url: (p) => `/api/query/callers/${encodeURIComponent(p.nodeId || "")}?kind=endpoint`, - }, - { - name: "run_cypher", - description: "Execute a raw Cypher query against the Neo4j graph (MCP protocol only)", - category: "analysis", - params: [{ name: "query", type: "string", description: "Cypher query string", required: true }], - url: "/api/cypher", - method: "POST", - }, - - // -- Security -- - { - name: "find_unprotected", - description: "Find endpoints without auth guards", - category: "security", params: [], url: "/api/flow/auth?format=json", - }, - - // -- Code -- - { - name: "read_file", - description: "Read source file content with optional line range", - category: "code", - params: [ - { name: "path", type: "string", description: "File path (relative to codebase root)", required: true }, - { name: "startLine", type: "number", description: "Start line number" }, - { name: "endLine", type: "number", description: "End line number" }, - ], - url: (p) => - `/api/file?path=${encodeURIComponent(p.path || "")}${p.startLine ? `&startLine=${p.startLine}` : ""}${p.endLine ? `&endLine=${p.endLine}` : ""}`, - }, -]; - -/** Group tools by category ID. */ -export function toolsByCategory(): Record { - const result: Record = {}; - for (const cat of CATEGORIES) result[cat.id] = []; - for (const tool of TOOLS) { - if (!result[tool.category]) result[tool.category] = []; - result[tool.category].push(tool); - } - return result; -} diff --git a/src/main/frontend/src/main.tsx b/src/main/frontend/src/main.tsx deleted file mode 100644 index 4ab5648f..00000000 --- a/src/main/frontend/src/main.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import { BrowserRouter } from 'react-router-dom'; -import { ToastRegion } from '@ossrandom/design-system'; -import AppRoot from './App'; -import { ThemeProvider } from './context/ThemeContext'; -import '@ossrandom/design-system/styles.css'; -import './index.css'; - -ReactDOM.createRoot(document.getElementById('root')!).render( - - - - - - - - -); diff --git a/src/main/frontend/src/pages/Dashboard.tsx b/src/main/frontend/src/pages/Dashboard.tsx deleted file mode 100644 index 3f80f3a6..00000000 --- a/src/main/frontend/src/pages/Dashboard.tsx +++ /dev/null @@ -1,485 +0,0 @@ -import { useState, useMemo, useCallback, useEffect, useRef, Fragment } from 'react'; -import { - Card, Spin, Alert, Modal, Drawer, Stat, Table, ScrollDiv, Space, -} from '@ossrandom/design-system'; -import { Treemap } from '@ossrandom/design-system/charts'; -import type { TreemapNode } from '@ossrandom/design-system/charts'; -import { useApi } from '@/hooks/useApi'; -import { api } from '@/lib/api'; -import type { StatsResponse, FileTreeResponse, FileTreeNode } from '@/types/api'; -import { Icon } from '@/components/Icons'; - -// ── Stats helpers ── - -function flattenToRecord(val: unknown): Record { - if (!val || typeof val !== 'object') return {}; - const result: Record = {}; - for (const [k, v] of Object.entries(val as Record)) { - if (typeof v === 'number') result[k] = v; - else if (typeof v === 'object' && v !== null && !Array.isArray(v)) - for (const [k2, v2] of Object.entries(v as Record)) - if (typeof v2 === 'number') result[`${k}/${k2}`] = v2; - } - return result; -} - -function sumValues(rec: Record): number { - return Object.values(rec).reduce((a, b) => a + b, 0); -} - -function isComputedStats(s: StatsResponse): s is StatsResponse & { - graph: { nodes: number; edges: number; files: number }; - languages: Record; frameworks: Record; - connections?: unknown; auth?: unknown; architecture?: unknown; -} { return 'graph' in s; } - -interface BreakdownRow { key: string; name: string; count: number } - -function StatCard({ title, value, icon, detail, detailTitle }: { - title: string; value: number | string; icon: React.ReactNode; - detail?: Record; detailTitle?: string; -}) { - const [open, setOpen] = useState(false); - const hasDetail = detail && Object.keys(detail).length > 0 && sumValues(detail) > 0; - const tableData: BreakdownRow[] = hasDetail - ? Object.entries(detail!).sort((a, b) => b[1] - a[1]).map(([name, count]) => ({ key: name, name, count })) - : []; - - const cardEl = ( - - {icon}{title}} - value={value} - /> - - ); - - return ( - <> - {hasDetail ? ( -
setOpen(true)} - onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setOpen(true); } }} - style={{ cursor: 'pointer', height: '100%' }}> - {cardEl} -
- ) : cardEl} - setOpen(false)} title={detailTitle ?? title} size="md"> - - - rowKey="key" - density="compact" - data={tableData} - columns={[ - { key: 'name', title: 'Name', dataKey: 'name' }, - { key: 'count', title: 'Count', dataKey: 'count', align: 'right', - render: (v) => (typeof v === 'number' ? v.toLocaleString() : String(v)) }, - ]} - /> - - - - ); -} - -// ── Treemap data ── - -const LANG_COLORS: Record = { - java: '#b07219', python: '#3572A5', typescript: '#3178c6', javascript: '#f1e05a', - go: '#00ADD8', csharp: '#178600', rust: '#dea584', kotlin: '#A97BFF', - yaml: '#cb171e', json: '#555', ruby: '#701516', scala: '#c22d40', - cpp: '#f34b7d', shell: '#89e051', markdown: '#083fa1', html: '#e34c26', - css: '#563d7c', sql: '#e38c00', proto: '#60a0b0', dockerfile: '#384d54', - other: '#888', -}; -const EXT_TO_LANG: Record = { - java: 'java', py: 'python', ts: 'typescript', tsx: 'typescript', - js: 'javascript', jsx: 'javascript', go: 'go', cs: 'csharp', - rs: 'rust', kt: 'kotlin', yml: 'yaml', yaml: 'yaml', - json: 'json', rb: 'ruby', scala: 'scala', cpp: 'cpp', - h: 'cpp', sh: 'shell', md: 'markdown', html: 'html', - css: 'css', sql: 'sql', proto: 'proto', -}; - -function inferLang(name: string): string { - return EXT_TO_LANG[name.split('.').pop()?.toLowerCase() ?? ''] ?? 'other'; -} - -function dominantLang(nodes: FileTreeNode[]): string { - const counts: Record = {}; - (function walk(items: FileTreeNode[]) { - for (const item of items) { - if (item.type === 'file') { const l = inferLang(item.name); counts[l] = (counts[l] ?? 0) + (item.nodeCount || 1); } - if (item.children) walk(item.children); - } - })(nodes); - return Object.entries(counts).sort((a, b) => b[1] - a[1])[0]?.[0] ?? 'other'; -} - -function collapseTree(nodes: FileTreeNode[]): FileTreeNode[] { - return nodes.map(n => { - if (n.type !== 'directory' || !n.children || n.children.length === 0) return n; - let current = n, collapsedName = n.name; - while (current.type === 'directory' && current.children && current.children.length === 1 - && current.children[0].type === 'directory' && current.children[0].children && current.children[0].children.length > 0) { - current = current.children[0]; collapsedName += '/' + current.name; - } - return { ...current, name: collapsedName, children: collapseTree(current.children ?? []), nodeCount: n.nodeCount }; - }); -} - -function buildTreemapTree( - nodes: FileTreeNode[], - parentPath: string, - pathMap: WeakMap, - truncatedDirMap: WeakMap, -): TreemapNode[] { - // Sort children by name so the treemap layout is stable across page - // loads regardless of API result ordering. d3-hierarchy's squarified - // layout is deterministic in input order; so deterministic input ⇒ - // deterministic visual. - const sorted = [...nodes].sort((a, b) => a.name.localeCompare(b.name)); - const out: TreemapNode[] = []; - for (const n of sorted) { - const fullPath = parentPath ? `${parentPath}/${n.name}` : n.name; - if (n.nodeCount <= 0 && (!n.children || n.children.length === 0)) continue; - if (n.type === 'directory' && n.children && n.children.length > 0) { - const children = buildTreemapTree(n.children, fullPath, pathMap, truncatedDirMap); - if (children.length === 0) continue; - const node: TreemapNode = { - name: n.name, - children, - color: LANG_COLORS[dominantLang(n.children)] ?? '#666', - }; - pathMap.set(node, fullPath); - out.push(node); - } else { - // A directory with no children but nodeCount > 0 is the backend's depth-cap - // marker — descendants exist but weren't fetched. Render as a leaf and - // flag for lazy expansion on click (Phase 2/3 path-rooted refetch). - const isTruncatedDir = n.type === 'directory' && n.nodeCount > 0; - const node: TreemapNode = { - name: n.name, - value: Math.max(n.nodeCount, 1), - color: LANG_COLORS[isTruncatedDir ? 'other' : inferLang(n.name)] ?? '#666', - }; - pathMap.set(node, fullPath); - if (isTruncatedDir) truncatedDirMap.set(node, true); - out.push(node); - } - } - return out; -} - -/** - * Walk down to leaves and sum their values. Used when flattening the visible - * level for label rendering: the design-system Treemap canvas only paints - * names on leaf cells (its `isLeaf` check guards label drawing), so - * directories at the focused level have to be rendered as leaves with a - * pre-aggregated value to keep the cell-sizing accurate. - */ -function aggregateLeafValue(node: TreemapNode): number { - if (!node.children || node.children.length === 0) return node.value ?? 1; - let sum = 0; - for (const c of node.children) sum += aggregateLeafValue(c); - return sum; -} - -/** - * Splice a freshly-fetched subtree into the right slot of the existing tree. - * Matches by absolute filesystem path (which the backend emits unchanged in - * `path` for both root and path-rooted responses), then replaces the - * directory's children. Returns a new tree array — the caller should treat - * the result as immutable. - */ -function mergeSubtree( - tree: FileTreeNode[], - fsPath: string, - subtree: FileTreeNode[], -): FileTreeNode[] { - return tree.map(n => { - if (n.path === fsPath && n.type === 'directory') { - return { ...n, children: subtree }; - } - if (n.children && n.children.length > 0 && fsPath.startsWith(n.path + '/')) { - return { ...n, children: mergeSubtree(n.children, fsPath, subtree) }; - } - return n; - }); -} - -function useViewportHeight(offset: number): number { - const [h, setH] = useState(() => (typeof window === 'undefined' ? 600 : window.innerHeight - offset)); - useEffect(() => { - const onResize = () => setH(window.innerHeight - offset); - window.addEventListener('resize', onResize); - return () => window.removeEventListener('resize', onResize); - }, [offset]); - return Math.max(360, h); -} - -// ── Main ── - -export default function Dashboard() { - // Stats - const { data: stats, loading: statsLoading, error: statsError } = useApi(() => api.getStats(), []); - const { data: kinds } = useApi(() => api.getKinds(), []); - const { data: detailed } = useApi(() => api.getDetailedStats('all'), []); - const computed = stats && isComputedStats(stats) ? stats : null; - const qs = stats && !isComputedStats(stats) ? stats as { node_count: number; edge_count: number } : null; - const nodeCount = computed?.graph?.nodes ?? qs?.node_count ?? 0; - const edgeCount = computed?.graph?.edges ?? qs?.edge_count ?? 0; - const fileCount = computed?.graph?.files ?? 0; - const languages = flattenToRecord(computed?.languages); - const frameworks = flattenToRecord(computed?.frameworks); - const connections = flattenToRecord(computed?.connections); - const auth = flattenToRecord(computed?.auth); - const architecture = flattenToRecord(computed?.architecture); - const nodeKindBreakdown: Record = {}; - if (kinds?.kinds) for (const k of kinds.kinds) nodeKindBreakdown[k.kind] = k.count; - const edgeKindBreakdown: Record = {}; - if (computed) { - const g = (computed as unknown as Record).graph as Record | undefined; - if (g?.edges_by_kind && typeof g.edges_by_kind === 'object') Object.assign(edgeKindBreakdown, flattenToRecord(g.edges_by_kind)); - } - if (detailed && typeof detailed === 'object' && Object.keys(edgeKindBreakdown).length === 0) { - const g = (detailed as Record).graph as Record | undefined; - if (g?.edges_by_kind && typeof g.edges_by_kind === 'object') Object.assign(edgeKindBreakdown, flattenToRecord(g.edges_by_kind)); - } - - // Treemap height — header(56) + content padding(32) + stats row(~110) + - // breadcrumb(38) + gaps(24) - const treemapHeight = useViewportHeight(56 + 32 + 110 + 38 + 24); - - // Treemap. Initial fetch caps at depth 8 — enough for a fully-qualified Java - // path (src/main/java/io/github////File.java = 8 segments) - // and the typical TS/Python/Go layouts. Directories beyond depth 8 come - // back as truncation markers (type=directory, children=[], nodeCount>0); - // when the user clicks one, we fetch its subtree on demand via the - // path-rooted /api/file-tree?path=… endpoint and splice it into place. - const [treeData, setTreeData] = useState(null); - const [treeLoading, setTreeLoading] = useState(true); - const [subtreeLoading, setSubtreeLoading] = useState(false); - const loadedPathsRef = useRef>(new Set()); - - useEffect(() => { - let cancelled = false; - setTreeLoading(true); - api.getFileTree(8) - .then(r => { if (!cancelled) setTreeData(r); }) - .catch(() => { /* surface via empty-tree state */ }) - .finally(() => { if (!cancelled) setTreeLoading(false); }); - return () => { cancelled = true; }; - }, []); - - const ensureSubtreeLoaded = useCallback(async (fsPath: string) => { - if (loadedPathsRef.current.has(fsPath)) return; - // Mark eagerly to dedupe concurrent clicks; revert on failure so the - // user can retry by clicking again. - loadedPathsRef.current.add(fsPath); - setSubtreeLoading(true); - try { - const sub = await api.getFileTree(8, fsPath); - setTreeData(prev => prev - ? { ...prev, tree: mergeSubtree(prev.tree, fsPath, sub.tree) } - : prev); - } catch { - loadedPathsRef.current.delete(fsPath); - } finally { - setSubtreeLoading(false); - } - }, []); - - const { treemapRoot, pathMap, truncatedDirMap } = useMemo(() => { - const pMap = new WeakMap(); - const tMap = new WeakMap(); - const children = buildTreemapTree(collapseTree(treeData?.tree ?? []), '', pMap, tMap); - const root: TreemapNode = { name: 'root', children }; - return { treemapRoot: root, pathMap: pMap, truncatedDirMap: tMap }; - }, [treeData]); - - // Drill state — names of the directories we've drilled into, in order. - // Empty = full tree. Single-click on a directory pushes; clicking a - // breadcrumb segment slices back to that depth. - const [focusPath, setFocusPath] = useState([]); - - // Reset focus only on a fresh full-tree load (total_files indicates the - // initial fetch landed). Subtree-merge updates also bump treeData but keep - // total_files unchanged, so the user's drill position survives lazy loads. - const totalFiles = treeData?.total_files; - useEffect(() => { setFocusPath([]); }, [totalFiles]); - - // Walk treemapRoot along focusPath. Falls back to root if any segment is - // missing (defensive — shouldn't happen since focusPath only ever holds - // names we just clicked). - const focusedRoot = useMemo(() => { - let cur: TreemapNode = treemapRoot; - for (const name of focusPath) { - const child = cur.children?.find(c => c.name === name); - if (!child) return treemapRoot; - cur = child; - } - return cur; - }, [treemapRoot, focusPath]); - - // Render-only flat copy of the focused level. The design-system Treemap - // only paints names on leaf cells (its canvas path checks `!n.children?.length` - // before drawing the label), so directories at the visible level — which - // legitimately have children for drill-down — appear as unlabelled - // rectangles. Strip children for the render pass to satisfy the leaf - // check; the original TreemapNode (with intact children) stays in - // `focusedRoot` and is recovered via `renderToOriginal` in the click - // handler so drill-down still works. - const { focusedRootForRender, renderToOriginal } = useMemo(() => { - const map = new WeakMap(); - const flat = (focusedRoot.children ?? []).map(c => { - if (c.children && c.children.length > 0) { - const rendered: TreemapNode = { - name: c.name, - value: aggregateLeafValue(c), - color: c.color, - }; - map.set(rendered, c); - return rendered; - } - // Files and truncated-directory markers are already leaves; preserve - // identity so existing pathMap / truncatedDirMap lookups keep working. - return c; - }); - return { - focusedRootForRender: { name: focusedRoot.name, children: flat }, - renderToOriginal: map, - }; - }, [focusedRoot]); - - // File viewer - const [fileDrawer, setFileDrawer] = useState<{ path: string; content: string } | null>(null); - const [fileLoading, setFileLoading] = useState(false); - const onTreemapNodeClick = useCallback(async (clicked: TreemapNode) => { - // Resolve the original TreemapNode behind the rendered (children-stripped) - // cell so pathMap / truncatedDirMap / drill-down keep working. - const node = renderToOriginal.get(clicked) ?? clicked; - // Directory with children — drill down one level. - if (node.children && node.children.length > 0) { - setFocusPath(prev => [...prev, node.name]); - return; - } - // Truncated directory (depth-cap marker) — fetch its subtree, then drill in. - if (truncatedDirMap.get(node)) { - const fsPath = pathMap.get(node); - if (!fsPath) return; - await ensureSubtreeLoaded(fsPath); - setFocusPath(prev => [...prev, node.name]); - return; - } - // Leaf — open file in drawer. - const filePath = pathMap.get(node); - if (!filePath) return; - setFileLoading(true); - setFileDrawer({ path: filePath, content: '' }); - try { setFileDrawer({ path: filePath, content: await api.readFile(filePath) }); } - catch { setFileDrawer({ path: filePath, content: '// Could not load file' }); } - finally { setFileLoading(false); } - }, [pathMap, truncatedDirMap, renderToOriginal, ensureSubtreeLoaded]); - - if (statsLoading || treeLoading) { - return
; - } - if (statsError) { - return {statsError}; - } - - return ( -
-
- {[ - { t: 'Nodes', v: nodeCount.toLocaleString(), i: , d: nodeKindBreakdown, dt: 'Nodes by Kind' }, - { t: 'Edges', v: edgeCount.toLocaleString(), i: , d: edgeKindBreakdown, dt: 'Edges by Kind' }, - { t: 'Files', v: fileCount.toLocaleString(), i: }, - { t: 'Languages', v: Object.keys(languages).length, i: , d: languages, dt: 'Languages' }, - { t: 'Frameworks', v: Object.keys(frameworks).length, i: , d: frameworks, dt: 'Frameworks' }, - { t: 'Connections', v: sumValues(connections), i: , d: connections, dt: 'Connections' }, - { t: 'Security', v: sumValues(auth), i: , d: auth, dt: 'Auth Patterns' }, - { t: 'Code Structure', v: sumValues(architecture), i: , d: architecture, dt: 'Code Structure' }, - ].map(s => ( - - ))} -
- -
- - {focusPath.map((seg, i) => ( - - / - - - ))} - {subtreeLoading && ( - - loading subtree… - - )} -
- -
- {focusedRoot.children && focusedRoot.children.length > 0 ? ( - v.toLocaleString()} - /> - ) : ( - -
- {treemapRoot.children && treemapRoot.children.length > 0 - ? 'This folder is empty. Use the breadcrumb above to go back.' - : 'No file data. Run index + enrich first.'} -
-
- )} -
- - setFileDrawer(null)} - placement="right" - width="60vw" - title={fileDrawer?.path} - > - {fileLoading ? ( -
- ) : ( -
-            {fileDrawer?.content}
-          
- )} -
-
- ); -} diff --git a/src/main/frontend/src/types/api.ts b/src/main/frontend/src/types/api.ts deleted file mode 100644 index 70d7a99c..00000000 --- a/src/main/frontend/src/types/api.ts +++ /dev/null @@ -1,156 +0,0 @@ -// Matches StatsService.computeStats() output (primary, from H2 cache) -export interface ComputedStatsResponse { - graph: { nodes: number; edges: number; files: number }; - languages: Record; - frameworks: Record; - infra: { - databases: Record; - messaging: Record; - cloud: Record; - }; - connections: { - rest: { total: number; by_method: Record }; - grpc: number; - websocket: number; - producers: number; - consumers: number; - }; - auth: Record; - architecture: Record; -} - -// Matches QueryService.getStats() output (fallback, from Neo4j) -export interface QueryStatsResponse { - node_count: number; - edge_count: number; - nodes_by_kind: Record; - nodes_by_layer: Record; -} - -// Union type -- the /api/stats endpoint may return either format -export type StatsResponse = ComputedStatsResponse | QueryStatsResponse; - -// Type guard -export function isComputedStats(s: StatsResponse): s is ComputedStatsResponse { - return 'graph' in s; -} - -export interface DetailedStatsResponse { - architecture?: Record; - frameworks?: Record; - infrastructure?: Record; - auth?: Record; - connections?: Record; - [key: string]: unknown; -} - -export interface CategoryStats { - [key: string]: unknown; -} - -export interface KindEntry { - kind: string; - count: number; -} - -export interface KindsResponse { - kinds: KindEntry[]; - total: number; -} - -export interface NodeResponse { - id: string; - kind: string; - label: string; - fqn?: string; - module?: string; - file_path?: string; - line_start?: number; - line_end?: number; - layer?: string; - annotations?: string[]; - properties?: Record; -} - -export interface NodesListResponse { - kind?: string; - total?: number; - offset: number; - limit: number; - nodes: NodeResponse[]; - count?: number; -} - -export interface EdgeResponse { - id: string; - kind: string; - source: string; - target?: string; -} - -export interface EdgesListResponse { - edges: EdgeResponse[]; - count: number; - total: number; -} - -export interface SearchResult { - id: string; - kind: string; - label?: string; - name?: string; - score?: number; - file_path?: string; - filePath?: string; -} - -export interface FileTreeNode { - name: string; - path: string; - type: 'file' | 'directory'; - nodeCount: number; - children?: FileTreeNode[]; -} - -export interface FileTreeResponse { - tree: FileTreeNode[]; - total_files: number; - truncated: boolean; -} - -// Topology API types -export interface TopologyService { - name: string; - nodeCount?: number; - layer?: string; - modules?: string[]; - language?: string; - framework?: string; -} - -export interface TopologyDependency { - source: string; - target: string; - kind?: string; - count?: number; -} - -export interface TopologyResponse { - services: TopologyService[]; - dependencies: TopologyDependency[]; -} - -// Ego graph API types -export interface EgoGraphResponse { - center: string; - nodes: NodeResponse[]; - edges: EdgeResponse[]; - radius?: number; -} - -// Neighbors API types -export interface NeighborsResponse { - node: NodeResponse; - incoming: Array<{ edge: EdgeResponse; node: NodeResponse }>; - outgoing: Array<{ edge: EdgeResponse; node: NodeResponse }>; -} diff --git a/src/main/frontend/test-results/.last-run.json b/src/main/frontend/test-results/.last-run.json deleted file mode 100644 index cbcc1fba..00000000 --- a/src/main/frontend/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "passed", - "failedTests": [] -} \ No newline at end of file diff --git a/src/main/frontend/tests/e2e/accessibility.spec.ts b/src/main/frontend/tests/e2e/accessibility.spec.ts deleted file mode 100644 index 09496b88..00000000 --- a/src/main/frontend/tests/e2e/accessibility.spec.ts +++ /dev/null @@ -1,210 +0,0 @@ -/** - * Accessibility tests — WCAG 2.1 AA compliance. - * - * Covers: - * AC-3 No WCAG 2.1 AA accessibility violations - * - * Uses @axe-core/playwright for automated ARIA/contrast/role checks, - * plus manual keyboard navigation assertions. - * - * References: - * https://www.deque.com/axe/core-documentation/api-documentation/ - * https://www.w3.org/WAI/WCAG21/quickref/?versions=2.1&levels=aa - */ - -import { test, expect } from '@playwright/test'; -import AxeBuilder from '@axe-core/playwright'; -import { gotoRoute, mockStats, mockGraphData, ROUTES } from '../utils/test-helpers'; - -// ── Automated axe audit per page ────────────────────────────────────────────── - -const PAGES = [ - { name: 'Dashboard', route: ROUTES.dashboard }, - { name: 'Code Graph', route: ROUTES.graph }, - { name: 'Explorer', route: ROUTES.explorer }, - { name: 'MCP Console', route: ROUTES.console }, - { name: 'API Docs', route: ROUTES.apiDocs }, -] as const; - -for (const { name, route } of PAGES) { - test(`${name}: no WCAG 2.1 AA violations (axe audit)`, async ({ page }) => { - await mockStats(page); - await mockGraphData(page, 100); - await gotoRoute(page, route); - - const results = await new AxeBuilder({ page }) - .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) - // Suppress known acceptable false positives from third-party libs - .exclude('[data-testid="swagger-ui-iframe"]') // Swagger UI manages its own a11y - .analyze(); - - expect(results.violations).toHaveLength(0); - }); -} - -// ── Keyboard navigation ─────────────────────────────────────────────────────── - -test.describe('Keyboard navigation', () => { - test('all nav links reachable via Tab from header', async ({ page }) => { - await mockStats(page); - await gotoRoute(page, ROUTES.dashboard); - - // Focus the first interactive element in the document - await page.keyboard.press('Tab'); - - const navLabels = ['Dashboard', 'Code Graph', 'Explorer', 'Console', 'API Docs']; - let foundCount = 0; - - for (let i = 0; i < 30; i++) { - const focused = await page.evaluate(() => document.activeElement?.textContent?.trim() ?? ''); - if (navLabels.includes(focused)) foundCount++; - if (foundCount === navLabels.length) break; - await page.keyboard.press('Tab'); - } - - expect(foundCount).toBe(navLabels.length); - }); - - test('no keyboard trap in sidebar', async ({ page }) => { - await mockStats(page); - await gotoRoute(page, ROUTES.dashboard); - - // Tab through the sidebar without getting stuck - const visitedTags: string[] = []; - for (let i = 0; i < 30; i++) { - await page.keyboard.press('Tab'); - const tag = await page.evaluate(() => document.activeElement?.tagName ?? ''); - visitedTags.push(tag); - } - - // Focus should eventually move into main (not loop in sidebar forever) - const hasMain = await page.evaluate(() => { - const el = document.activeElement; - return !!el?.closest('main'); - }); - expect(hasMain).toBe(true); - }); - - test('theme toggle is keyboard accessible', async ({ page }) => { - await mockStats(page); - await gotoRoute(page, ROUTES.dashboard); - - // Find the theme toggle button via Tab - const themeToggle = page.getByRole('button', { name: /toggle theme|dark mode|light mode/i }); - await themeToggle.focus(); - await expect(themeToggle).toBeFocused(); - - // Activate via Enter - await page.keyboard.press('Enter'); - // The html class should have flipped - const cls = await page.locator('html').getAttribute('class') ?? ''; - // Just verify no exception was thrown and page is still interactive - await expect(page.locator('main')).toBeVisible(); - void cls; // used to avoid lint warning - }); - - test('search bar is reachable and activatable via keyboard', async ({ page }) => { - await mockStats(page); - await gotoRoute(page, ROUTES.dashboard); - - const searchBox = page.getByRole('searchbox'); - await searchBox.focus(); - await expect(searchBox).toBeFocused(); - await page.keyboard.type('test'); - await expect(searchBox).toHaveValue('test'); - }); - - test('modal/dialog traps focus correctly', async ({ page }) => { - await mockStats(page); - await mockGraphData(page, 20); - await gotoRoute(page, ROUTES.graph); - - // Open node detail (assuming a dialog opens — may be the right panel) - const detailDialog = page.locator('[role="dialog"]'); - if (!(await detailDialog.isVisible())) { - // Try to open one by clicking a node in the graph area - const graph = page.locator('[data-testid="graph-container"]'); - const box = await graph.boundingBox(); - if (box) await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2); - } - - if (await detailDialog.isVisible()) { - // Tab should cycle within the dialog - await page.keyboard.press('Tab'); - const focusedInDialog = await page.evaluate(() => { - const el = document.activeElement; - return !!el?.closest('[role="dialog"]'); - }); - expect(focusedInDialog).toBe(true); - - // Escape should close the dialog - await page.keyboard.press('Escape'); - await expect(detailDialog).not.toBeVisible(); - } - }); -}); - -// ── ARIA labels ─────────────────────────────────────────────────────────────── - -test.describe('ARIA labels', () => { - test('navigation landmark is labelled', async ({ page }) => { - await mockStats(page); - await gotoRoute(page, ROUTES.dashboard); - // There must be a