diff --git a/src/codegen.ts b/src/codegen.ts index 59eb5f9..f7ba883 100644 --- a/src/codegen.ts +++ b/src/codegen.ts @@ -1049,7 +1049,7 @@ export class CodeGenerator { result += this.indent(`const ${name} = {};\n`); // Generate namespace body - if (node.body && node.body.statements) { + if (node.body?.statements) { for (const stmt of node.body.statements) { const isExported = (stmt as Statement & { exported?: boolean }).exported; @@ -1127,7 +1127,7 @@ export class CodeGenerator { return (stmt as FunctionDeclaration).name.name; case 'VariableDeclaration': { const varDecl = stmt as VariableDeclaration; - if (varDecl.identifier && varDecl.identifier.type === 'Identifier') { + if (varDecl.identifier?.type === 'Identifier') { return varDecl.identifier.name; } break; @@ -1150,7 +1150,7 @@ export class CodeGenerator { let classBody = ''; // Generate class members - if (node.body && node.body.body) { + if (node.body?.body) { const members = node.body.body .map(member => { switch (member.type) { @@ -1192,7 +1192,7 @@ export class CodeGenerator { } else { // Regular methods have a body // Handle cases where body might be null or undefined - if (!node.value || !node.value.body) { + if (!node.value?.body) { return this.indent(`${isStatic}${methodName}(${params}) {}`); } const body = this.generateBlockStatement(node.value.body); diff --git a/src/config.ts b/src/config.ts index 81af91b..cfa5339 100644 --- a/src/config.ts +++ b/src/config.ts @@ -174,7 +174,7 @@ function validateModuleSystem(config: unknown, basePath = 'moduleSystem'): Confi function validateModuleSystemTopLevel(config: object, basePath: string): ConfigValidationError[] { const errors: ConfigValidationError[] = []; - const knownTop = [ + const knownTop = new Set([ 'resolution', 'loading', 'compilation', @@ -183,10 +183,10 @@ function validateModuleSystemTopLevel(config: object, basePath: string): ConfigV 'logger', 'managementServer', 'managementPort', - ]; + ]); for (const key of Object.keys(config)) { - if (!knownTop.includes(key)) { + if (!knownTop.has(key)) { errors.push({ path: `${basePath}.${key}`, message: `unknown property` }); } } diff --git a/src/core/application-layer.ts b/src/core/application-layer.ts index 18090e7..d614b1d 100644 --- a/src/core/application-layer.ts +++ b/src/core/application-layer.ts @@ -382,8 +382,6 @@ export class CompilationUseCase implements ICompilationUseCase { metrics, }; } catch (error) { - const totalTime = performance.now() - startTime; - errors.push({ message: `Compilation failed: ${error}`, line: 0, diff --git a/src/core/modular-lexer-compatible.ts b/src/core/modular-lexer-compatible.ts index 2589c8f..704d1ca 100644 --- a/src/core/modular-lexer-compatible.ts +++ b/src/core/modular-lexer-compatible.ts @@ -374,7 +374,7 @@ export class OperatorRecognizer extends BaseTokenRecognizer { canRecognize(input: string, position: number): boolean { const char = this.peek(input, position); // Check if any operator starts with this character - return this.sortedOperators.some(op => op[0] === char); + return this.sortedOperators.some(op => op.startsWith(char)); } recognize( diff --git a/src/lexer.ts b/src/lexer.ts index eec21ef..e70d717 100644 --- a/src/lexer.ts +++ b/src/lexer.ts @@ -275,6 +275,20 @@ export class Lexer { return this.nextToken(); } + const switchResult = this.handleSwitchCharacters(char, startLine, startColumn); + if (switchResult) return switchResult; + + const operatorResult = this.handleComparisonAndBitwiseOperators(char, startLine, startColumn); + if (operatorResult) return operatorResult; + + return this.handleLiteralsAndIdentifiers(char, startLine, startColumn); + } + + private handleSwitchCharacters( + char: string, + startLine: number, + startColumn: number + ): Token | null { switch (char) { case '+': return this.handlePlusOperator(); @@ -311,22 +325,46 @@ export class Lexer { this.line++; this.column = 1; return this.createToken(TokenType.NEWLINE, '\n', startLine, startColumn); + default: + return null; } + } - if (char === '=') return this.handleEqualOperator(startLine, startColumn); - if (char === '!') return this.handleNotOperator(startLine, startColumn); - if (char === '<') return this.handleLessThanOperator(startLine, startColumn); - if (char === '>') return this.handleGreaterThanOperator(startLine, startColumn); - if (char === '&') return this.handleAmpersandOperator(startLine, startColumn); - if (char === '|') return this.handlePipeOperator(startLine, startColumn); - if (char === '^') return this.handleCaretOperator(startLine, startColumn); - if (char === '?') return this.handleQuestionOperator(startLine, startColumn); - - if (char === '~') { - this.advance(); - return this.createToken(TokenType.BITWISE_NOT, '~', startLine, startColumn); + private handleComparisonAndBitwiseOperators( + char: string, + startLine: number, + startColumn: number + ): Token | null { + switch (char) { + case '=': + return this.handleEqualOperator(startLine, startColumn); + case '!': + return this.handleNotOperator(startLine, startColumn); + case '<': + return this.handleLessThanOperator(startLine, startColumn); + case '>': + return this.handleGreaterThanOperator(startLine, startColumn); + case '&': + return this.handleAmpersandOperator(startLine, startColumn); + case '|': + return this.handlePipeOperator(startLine, startColumn); + case '^': + return this.handleCaretOperator(startLine, startColumn); + case '?': + return this.handleQuestionOperator(startLine, startColumn); + case '~': + this.advance(); + return this.createToken(TokenType.BITWISE_NOT, '~', startLine, startColumn); + default: + return null; } + } + private handleLiteralsAndIdentifiers( + char: string, + startLine: number, + startColumn: number + ): Token { if (char === '"' || char === "'") { return this.readString(char, startLine, startColumn); } diff --git a/src/module-system/module-registry.ts b/src/module-system/module-registry.ts index 5472f5e..d2ce8c9 100644 --- a/src/module-system/module-registry.ts +++ b/src/module-system/module-registry.ts @@ -424,17 +424,17 @@ export class ModuleRegistry { } // For relative paths, try to find the matching module - const possiblePaths = [ + const possiblePaths = new Set([ path.resolve(fromDir, specifier), path.resolve(fromDir, specifier + '.som'), path.resolve(fromDir, specifier + '.js'), path.resolve(fromDir, specifier, 'index.som'), path.resolve(fromDir, specifier, 'index.js'), - ]; + ]); // Find a registered module that matches one of the possible paths for (const mod of this.modules.values()) { - if (possiblePaths.includes(mod.resolvedPath)) { + if (possiblePaths.has(mod.resolvedPath)) { return mod.id; } } diff --git a/src/module-system/module-system.ts b/src/module-system/module-system.ts index c21ed1d..b49a323 100644 --- a/src/module-system/module-system.ts +++ b/src/module-system/module-system.ts @@ -259,9 +259,8 @@ export class ModuleSystem { this.validateResourceLimits(options, errors); if (errors.length > 0) { - throw new Error( - `ModuleSystem configuration validation failed:\n${errors.map((e, i) => ` ${i + 1}. ${e}`).join('\n')}` - ); + const formattedErrors = errors.map((e, i) => ` ${i + 1}. ${e}`).join('\n'); + throw new Error(`ModuleSystem configuration validation failed:\n${formattedErrors}`); } } @@ -765,7 +764,12 @@ export class ModuleSystem { const warningInfo = compilationResult.warnings.length > 0 - ? `\n\nWarnings (${compilationResult.warnings.length}):\n${compilationResult.warnings.map((w, i) => ` ${i + 1}. ${w}`).join('\n')}` + ? (() => { + const formattedWarnings = compilationResult.warnings + .map((w, i) => ` ${i + 1}. ${w}`) + .join('\n'); + return `\n\nWarnings (${compilationResult.warnings.length}):\n${formattedWarnings}`; + })() : ''; const errorMessage = `Bundle process failed with ${compilationResult.errors.length} error(s):\n\n${errorDetails}${warningInfo}`; @@ -1026,20 +1030,20 @@ export class ModuleSystem { const watcher = chokidar.watch(Array.from(watchRoots), watchConfig); - const supportedEvents: ModuleWatchEventType[] = [ + const supportedEvents = new Set([ 'add', 'change', 'unlink', 'addDir', 'unlinkDir', - ]; + ]); watcher.on('all', (event: string, changedPath: string) => { if (!options.onChange) { return; } - if (!supportedEvents.includes(event as ModuleWatchEventType)) { + if (!supportedEvents.has(event as ModuleWatchEventType)) { return; } diff --git a/src/module-system/prometheus-metrics.ts b/src/module-system/prometheus-metrics.ts index ee4b2bd..bc6fc23 100644 --- a/src/module-system/prometheus-metrics.ts +++ b/src/module-system/prometheus-metrics.ts @@ -213,7 +213,14 @@ export class PrometheusExporter { ); for (const [name, status] of Object.entries(cbStats)) { - const stateValue = status.state === 'closed' ? 0 : status.state === 'open' ? 1 : 2; + let stateValue: number; + if (status.state === 'closed') { + stateValue = 0; + } else if (status.state === 'open') { + stateValue = 1; + } else { + stateValue = 2; + } lines.push(`${this.prefix}_circuit_breaker_state{name="${name}"} ${stateValue} ${timestamp}`); lines.push( `${this.prefix}_circuit_breaker_failures{name="${name}"} ${status.failures} ${timestamp}` diff --git a/src/module-system/resource-limiter.ts b/src/module-system/resource-limiter.ts index 5fb801f..2b0627b 100644 --- a/src/module-system/resource-limiter.ts +++ b/src/module-system/resource-limiter.ts @@ -2,7 +2,7 @@ * Production-grade resource limiting and monitoring * Prevents memory exhaustion and resource leaks */ -import * as process from 'process'; +import * as process from 'node:process'; export interface ResourceLimits { /** Maximum heap memory in bytes (default: 1GB) */ @@ -33,7 +33,7 @@ export type ResourceWarningCallback = (_usage: ResourceUsage, _limit: string) => export class ResourceLimiter { private readonly limits: Required; private checkIntervalId?: ReturnType; - private warningCallbacks: ResourceWarningCallback[] = []; + private readonly warningCallbacks: ResourceWarningCallback[] = []; private moduleCount = 0; private fileHandleCount = 0; diff --git a/src/module-system/runtime-config.ts b/src/module-system/runtime-config.ts index 99bec97..3fa6a0b 100644 --- a/src/module-system/runtime-config.ts +++ b/src/module-system/runtime-config.ts @@ -2,8 +2,8 @@ * Runtime configuration and health check system * Provides dynamic configuration updates and HTTP management endpoints */ -import * as http from 'http'; -import * as url from 'url'; +import * as http from 'node:http'; +import * as url from 'node:url'; import { ModuleSystemMetrics } from './metrics'; import { CircuitBreakerManager } from './circuit-breaker'; import { LoggerFactory, LogLevel } from './logger'; diff --git a/src/module-system/signal-handler.ts b/src/module-system/signal-handler.ts index 31b5d64..8038de2 100644 --- a/src/module-system/signal-handler.ts +++ b/src/module-system/signal-handler.ts @@ -20,7 +20,7 @@ export interface SignalHandlerOptions { * Graceful shutdown manager for production systems */ export class SignalHandler { - private handlers: ShutdownHandler[] = []; + private readonly handlers: ShutdownHandler[] = []; private isShuttingDown = false; private readonly shutdownTimeout: number; private readonly logger?: SignalHandlerOptions['logger']; diff --git a/src/module-system/structured-logger.ts b/src/module-system/structured-logger.ts index ce49e3d..ca3cac0 100644 --- a/src/module-system/structured-logger.ts +++ b/src/module-system/structured-logger.ts @@ -1,7 +1,7 @@ /** * Structured logging with JSON support and correlation IDs */ -import { randomBytes } from 'crypto'; +import { randomBytes } from 'node:crypto'; export interface LogContext { correlationId?: string; @@ -207,7 +207,7 @@ export class StructuredLogger { * Global logger factory with structured logging support */ export class StructuredLoggerFactory { - private static loggers = new Map(); + private static readonly loggers = new Map(); private static globalOptions: StructuredLoggerOptions = { format: process.env.LOG_FORMAT === 'json' ? 'json' : 'text', level: (process.env.LOG_LEVEL as LogLevel) || 'info', diff --git a/src/parser.ts b/src/parser.ts index 3f2b94e..57a4cbe 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -83,9 +83,9 @@ export class Parser { private tokens: Token[]; private current: number = 0; private errors: string[] = []; - private importHandler: ImportHandler; - private declarationHandler: DeclarationHandler; - private loopHandler: LoopHandler; + private readonly importHandler: ImportHandler; + private readonly declarationHandler: DeclarationHandler; + private readonly loopHandler: LoopHandler; constructor(tokens: Token[]) { this.tokens = tokens; diff --git a/src/production-validator.ts b/src/production-validator.ts index 3d85c2c..9e15acf 100644 --- a/src/production-validator.ts +++ b/src/production-validator.ts @@ -3,8 +3,8 @@ * Implements AGENTS.md principle: "Fail fast, fail clearly" */ -import * as fs from 'fs'; -import * as path from 'path'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; export interface ValidationError { category: 'environment' | 'permissions' | 'configuration'; diff --git a/src/type-checker.ts b/src/type-checker.ts index 5e905d2..814d6fc 100644 --- a/src/type-checker.ts +++ b/src/type-checker.ts @@ -92,10 +92,10 @@ export class TypeChecker { private errors: TypeCheckError[] = []; private warnings: TypeCheckError[] = []; private symbolTable: Map = new Map(); - private interfaceTable: Map = new Map(); - private typeAliasTable: Map = new Map(); + private readonly interfaceTable: Map = new Map(); + private readonly typeAliasTable: Map = new Map(); - private sourceLines: string[] = []; + private readonly sourceLines: string[] = []; constructor(source?: string) { this.sourceLines = source ? source.split(/\r?\n/) : []; @@ -598,7 +598,7 @@ export class TypeChecker { // Check if it's a class type const classType = this.symbolTable.get(typeName); - if (classType && classType.kind === 'class') { + if (classType?.kind === 'class') { return classType; } @@ -712,12 +712,12 @@ export class TypeChecker { private inferArrayExpressionType(arrayExpr: ArrayExpression, targetType?: Type): Type { // If target type is a tuple, use bidirectional inference - if (targetType && targetType.kind === 'tuple' && targetType.types) { + if (targetType?.kind === 'tuple' && targetType.types) { return this.inferTupleTypeFromTarget(arrayExpr, targetType.types); } // If target is an array, infer array element type - if (targetType && targetType.kind === 'array') { + if (targetType?.kind === 'array') { const elementType = targetType.elementType || { kind: 'unknown' }; arrayExpr.elements.forEach((element: Expression) => this.inferExpressionType(element, elementType) @@ -743,21 +743,23 @@ export class TypeChecker { */ private getBaseType(type: Type): Type { if (type.kind === 'literal') { - const baseTypeName = - typeof type.value === 'string' - ? 'string' - : typeof type.value === 'number' - ? 'number' - : typeof type.value === 'boolean' - ? 'boolean' - : 'null'; + let baseTypeName: string; + if (typeof type.value === 'string') { + baseTypeName = 'string'; + } else if (typeof type.value === 'number') { + baseTypeName = 'number'; + } else if (typeof type.value === 'boolean') { + baseTypeName = 'boolean'; + } else { + baseTypeName = 'null'; + } return { kind: 'primitive', name: baseTypeName }; } return type; } private inferObjectType(objExpr: ObjectExpression, targetType?: Type): Type { - if (targetType && targetType.kind === 'interface') { + if (targetType?.kind === 'interface') { return targetType; } @@ -794,10 +796,10 @@ export class TypeChecker { } private inferCallType(callExpr: CallExpression): Type { - if (callExpr.callee && callExpr.callee.type === 'Identifier') { + if (callExpr.callee?.type === 'Identifier') { const functionName = (callExpr.callee as Identifier).name; const functionType = this.symbolTable.get(functionName); - if (functionType && functionType.kind === 'function' && functionType.returnType) { + if (functionType?.kind === 'function' && functionType.returnType) { return functionType.returnType; } } @@ -805,7 +807,7 @@ export class TypeChecker { } private inferNewExpressionType(newExpr: NewExpression): Type { - if (newExpr.callee && newExpr.callee.type === 'Identifier') { + if (newExpr.callee?.type === 'Identifier') { const className = (newExpr.callee as Identifier).name; // Handle built-in generic types: Map and Set @@ -828,7 +830,7 @@ export class TypeChecker { } const classType = this.symbolTable.get(className); - if (classType && classType.kind === 'class') { + if (classType?.kind === 'class') { // Return the actual class type with all its properties and baseType return classType; } @@ -840,14 +842,16 @@ export class TypeChecker { if (source.kind !== 'literal' || target.kind !== 'primitive') { return false; } - const baseType = - typeof source.value === 'string' - ? 'string' - : typeof source.value === 'number' - ? 'number' - : typeof source.value === 'boolean' - ? 'boolean' - : 'null'; + let baseType: string; + if (typeof source.value === 'string') { + baseType = 'string'; + } else if (typeof source.value === 'number') { + baseType = 'number'; + } else if (typeof source.value === 'boolean') { + baseType = 'boolean'; + } else { + baseType = 'null'; + } return baseType === target.name; }