fix(compiler-cli): remove the concept of an errored trait (#39967) · angular/angular@0aa35ec

@@ -181,15 +181,13 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

181181

const handler = this.handlersByName.get(priorTrait.handler.name)!;

182182

let trait: Trait<unknown, unknown, unknown> = Trait.pending(handler, priorTrait.detected);

183183184-

if (priorTrait.state === TraitState.ANALYZED || priorTrait.state === TraitState.RESOLVED) {

185-

trait = trait.toAnalyzed(priorTrait.analysis);

186-

if (trait.handler.register !== undefined) {

184+

if (priorTrait.state === TraitState.Analyzed || priorTrait.state === TraitState.Resolved) {

185+

trait = trait.toAnalyzed(priorTrait.analysis, priorTrait.analysisDiagnostics);

186+

if (trait.analysis !== null && trait.handler.register !== undefined) {

187187

trait.handler.register(record.node, trait.analysis);

188188

}

189-

} else if (priorTrait.state === TraitState.SKIPPED) {

189+

} else if (priorTrait.state === TraitState.Skipped) {

190190

trait = trait.toSkipped();

191-

} else if (priorTrait.state === TraitState.ERRORED) {

192-

trait = trait.toErrored(priorTrait.diagnostics);

193191

}

194192195193

record.traits.push(trait);

@@ -314,7 +312,7 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

314312

preanalysis = trait.handler.preanalyze(clazz, trait.detected.metadata) || null;

315313

} catch (err) {

316314

if (err instanceof FatalDiagnosticError) {

317-

trait.toErrored([err.toDiagnostic()]);

315+

trait.toAnalyzed(null, [err.toDiagnostic()]);

318316

return;

319317

} else {

320318

throw err;

@@ -332,7 +330,7 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

332330

protected analyzeTrait(

333331

clazz: ClassDeclaration, trait: Trait<unknown, unknown, unknown>,

334332

flags?: HandlerFlags): void {

335-

if (trait.state !== TraitState.PENDING) {

333+

if (trait.state !== TraitState.Pending) {

336334

throw new Error(`Attempt to analyze trait of ${clazz.name.text} in state ${

337335

TraitState[trait.state]} (expected DETECTED)`);

338336

}

@@ -343,26 +341,18 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

343341

result = trait.handler.analyze(clazz, trait.detected.metadata, flags);

344342

} catch (err) {

345343

if (err instanceof FatalDiagnosticError) {

346-

trait = trait.toErrored([err.toDiagnostic()]);

344+

trait.toAnalyzed(null, [err.toDiagnostic()]);

347345

return;

348346

} else {

349347

throw err;

350348

}

351349

}

352350353-

if (result.diagnostics !== undefined) {

354-

trait = trait.toErrored(result.diagnostics);

355-

} else if (result.analysis !== undefined) {

356-

// Analysis was successful. Trigger registration.

357-

if (trait.handler.register !== undefined) {

358-

trait.handler.register(clazz, result.analysis);

359-

}

360-361-

// Successfully analyzed and registered.

362-

trait = trait.toAnalyzed(result.analysis);

363-

} else {

364-

trait = trait.toSkipped();

351+

if (result.analysis !== undefined && trait.handler.register !== undefined) {

352+

trait.handler.register(clazz, result.analysis);

365353

}

354+355+

trait = trait.toAnalyzed(result.analysis ?? null, result.diagnostics ?? null);

366356

}

367357368358

resolve(): void {

@@ -372,19 +362,23 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

372362

for (let trait of record.traits) {

373363

const handler = trait.handler;

374364

switch (trait.state) {

375-

case TraitState.SKIPPED:

376-

case TraitState.ERRORED:

365+

case TraitState.Skipped:

377366

continue;

378-

case TraitState.PENDING:

367+

case TraitState.Pending:

379368

throw new Error(`Resolving a trait that hasn't been analyzed: ${clazz.name.text} / ${

380369

Object.getPrototypeOf(trait.handler).constructor.name}`);

381-

case TraitState.RESOLVED:

370+

case TraitState.Resolved:

382371

throw new Error(`Resolving an already resolved trait`);

383372

}

384373374+

if (trait.analysis === null) {

375+

// No analysis results, cannot further process this trait.

376+

continue;

377+

}

378+385379

if (handler.resolve === undefined) {

386380

// No resolution of this trait needed - it's considered successful by default.

387-

trait = trait.toResolved(null);

381+

trait = trait.toResolved(null, null);

388382

continue;

389383

}

390384

@@ -393,22 +387,14 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

393387

result = handler.resolve(clazz, trait.analysis as Readonly<unknown>);

394388

} catch (err) {

395389

if (err instanceof FatalDiagnosticError) {

396-

trait = trait.toErrored([err.toDiagnostic()]);

390+

trait = trait.toResolved(null, [err.toDiagnostic()]);

397391

continue;

398392

} else {

399393

throw err;

400394

}

401395

}

402396403-

if (result.diagnostics !== undefined && result.diagnostics.length > 0) {

404-

trait = trait.toErrored(result.diagnostics);

405-

} else {

406-

if (result.data !== undefined) {

407-

trait = trait.toResolved(result.data);

408-

} else {

409-

trait = trait.toResolved(null);

410-

}

411-

}

397+

trait = trait.toResolved(result.data ?? null, result.diagnostics ?? null);

412398413399

if (result.reexports !== undefined) {

414400

const fileName = clazz.getSourceFile().fileName;

@@ -436,12 +422,14 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

436422

for (const clazz of this.fileToClasses.get(sf)!) {

437423

const record = this.classes.get(clazz)!;

438424

for (const trait of record.traits) {

439-

if (trait.state !== TraitState.RESOLVED) {

425+

if (trait.state !== TraitState.Resolved) {

440426

continue;

441427

} else if (trait.handler.typeCheck === undefined) {

442428

continue;

443429

}

444-

trait.handler.typeCheck(ctx, clazz, trait.analysis, trait.resolution);

430+

if (trait.resolution !== null) {

431+

trait.handler.typeCheck(ctx, clazz, trait.analysis, trait.resolution);

432+

}

445433

}

446434

}

447435

}

@@ -450,15 +438,17 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

450438

for (const clazz of this.classes.keys()) {

451439

const record = this.classes.get(clazz)!;

452440

for (const trait of record.traits) {

453-

if (trait.state !== TraitState.RESOLVED) {

441+

if (trait.state !== TraitState.Resolved) {

454442

// Skip traits that haven't been resolved successfully.

455443

continue;

456444

} else if (trait.handler.index === undefined) {

457445

// Skip traits that don't affect indexing.

458446

continue;

459447

}

460448461-

trait.handler.index(ctx, clazz, trait.analysis, trait.resolution);

449+

if (trait.resolution !== null) {

450+

trait.handler.index(ctx, clazz, trait.analysis, trait.resolution);

451+

}

462452

}

463453

}

464454

}

@@ -475,19 +465,26 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

475465

let res: CompileResult[] = [];

476466477467

for (const trait of record.traits) {

478-

if (trait.state !== TraitState.RESOLVED) {

468+

if (trait.state !== TraitState.Resolved || trait.analysisDiagnostics !== null ||

469+

trait.resolveDiagnostics !== null) {

470+

// Cannot compile a trait that is not resolved, or had any errors in its declaration.

479471

continue;

480472

}

481473482474

const compileSpan = this.perf.start('compileClass', original);

483475476+477+

// `trait.resolution` is non-null asserted here because TypeScript does not recognize that

478+

// `Readonly<unknown>` is nullable (as `unknown` itself is nullable) due to the way that

479+

// `Readonly` works.

480+484481

let compileRes: CompileResult|CompileResult[];

485482

if (this.compilationMode === CompilationMode.PARTIAL &&

486483

trait.handler.compilePartial !== undefined) {

487-

compileRes = trait.handler.compilePartial(clazz, trait.analysis, trait.resolution);

484+

compileRes = trait.handler.compilePartial(clazz, trait.analysis, trait.resolution!);

488485

} else {

489486

compileRes =

490-

trait.handler.compileFull(clazz, trait.analysis, trait.resolution, constantPool);

487+

trait.handler.compileFull(clazz, trait.analysis, trait.resolution!, constantPool);

491488

}

492489493490

const compileMatchRes = compileRes;

@@ -522,7 +519,7 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

522519

const decorators: ts.Decorator[] = [];

523520524521

for (const trait of record.traits) {

525-

if (trait.state !== TraitState.RESOLVED) {

522+

if (trait.state !== TraitState.Resolved) {

526523

continue;

527524

}

528525

@@ -542,8 +539,12 @@ export class TraitCompiler implements ProgramTypeCheckAdapter {

542539

diagnostics.push(...record.metaDiagnostics);

543540

}

544541

for (const trait of record.traits) {

545-

if (trait.state === TraitState.ERRORED) {

546-

diagnostics.push(...trait.diagnostics);

542+

if ((trait.state === TraitState.Analyzed || trait.state === TraitState.Resolved) &&

543+

trait.analysisDiagnostics !== null) {

544+

diagnostics.push(...trait.analysisDiagnostics);

545+

}

546+

if (trait.state === TraitState.Resolved && trait.resolveDiagnostics !== null) {

547+

diagnostics.push(...trait.resolveDiagnostics);

547548

}

548549

}

549550

}