@@ -2294,6 +2294,22 @@ int swift::ide::api::deserializeSDKDump(StringRef dumpPath, StringRef OutputPath
2294
2294
return 0 ;
2295
2295
}
2296
2296
2297
+ void swift::ide::api::dumpModuleContent (ModuleDecl *MD, StringRef OutputFile,
2298
+ bool ABI) {
2299
+ CheckerOptions opts;
2300
+ opts.ABI = ABI;
2301
+ opts.SwiftOnly = true ;
2302
+ opts.AvoidLocation = true ;
2303
+ opts.AvoidToolArgs = true ;
2304
+ opts.Migrator = false ;
2305
+ opts.SkipOSCheck = false ;
2306
+ opts.Verbose = false ;
2307
+ SDKContext ctx (opts);
2308
+ SwiftDeclCollector collector (ctx);
2309
+ collector.lookupVisibleDecls ({MD});
2310
+ dumpSDKRoot (collector.getSDKRoot (), OutputFile);
2311
+ }
2312
+
2297
2313
int swift::ide::api::findDeclUsr (StringRef dumpPath, CheckerOptions Opts) {
2298
2314
std::error_code EC;
2299
2315
if (!fs::exists (dumpPath)) {
@@ -2323,3 +2339,301 @@ int swift::ide::api::findDeclUsr(StringRef dumpPath, CheckerOptions Opts) {
2323
2339
}
2324
2340
return 0 ;
2325
2341
}
2342
+
2343
+ void swift::ide::api::SDKNodeDeclType::diagnose (SDKNode *Right) {
2344
+ SDKNodeDecl::diagnose (Right);
2345
+ auto *R = dyn_cast<SDKNodeDeclType>(Right);
2346
+ if (!R)
2347
+ return ;
2348
+ auto Loc = R->getLoc ();
2349
+ if (getDeclKind () != R->getDeclKind ()) {
2350
+ emitDiag (Loc, diag::decl_kind_changed, getDeclKindStr (R->getDeclKind (),
2351
+ getSDKContext ().getOpts ().CompilerStyle ));
2352
+ return ;
2353
+ }
2354
+
2355
+ assert (getDeclKind () == R->getDeclKind ());
2356
+ auto DKind = getDeclKind ();
2357
+ switch (DKind) {
2358
+ case DeclKind::Class: {
2359
+ auto LSuperClass = getSuperClassName ();
2360
+ auto RSuperClass = R->getSuperClassName ();
2361
+ if (!LSuperClass.empty () && LSuperClass != RSuperClass) {
2362
+ if (RSuperClass.empty ()) {
2363
+ emitDiag (Loc, diag::super_class_removed, LSuperClass);
2364
+ } else if (!llvm::is_contained (R->getClassInheritanceChain (), LSuperClass)) {
2365
+ emitDiag (Loc, diag::super_class_changed, LSuperClass, RSuperClass);
2366
+ }
2367
+ }
2368
+
2369
+ // Check for @_hasMissingDesignatedInitializers and
2370
+ // @_inheritsConvenienceInitializers changes.
2371
+ if (isOpen () && R->isOpen ()) {
2372
+ // It's not safe to add new, invisible designated inits to open
2373
+ // classes.
2374
+ if (!hasMissingDesignatedInitializers () &&
2375
+ R->hasMissingDesignatedInitializers ())
2376
+ R->emitDiag (R->getLoc (), diag::added_invisible_designated_init);
2377
+ }
2378
+
2379
+ // It's not safe to stop inheriting convenience inits, it changes
2380
+ // the set of initializers that are available.
2381
+ if (!Ctx.checkingABI () &&
2382
+ inheritsConvenienceInitializers () &&
2383
+ !R->inheritsConvenienceInitializers ())
2384
+ R->emitDiag (R->getLoc (), diag::not_inheriting_convenience_inits);
2385
+ break ;
2386
+ }
2387
+ default :
2388
+ break ;
2389
+ }
2390
+ }
2391
+
2392
+ void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose (SDKNode *Right) {
2393
+ SDKNodeDecl::diagnose (Right);
2394
+ auto *R = dyn_cast<SDKNodeDeclAbstractFunc>(Right);
2395
+ if (!R)
2396
+ return ;
2397
+ auto Loc = R->getLoc ();
2398
+ if (!isThrowing () && R->isThrowing ()) {
2399
+ emitDiag (Loc, diag::decl_new_attr, Ctx.buffer (" throwing" ));
2400
+ }
2401
+ if (Ctx.checkingABI ()) {
2402
+ if (reqNewWitnessTableEntry () != R->reqNewWitnessTableEntry ()) {
2403
+ emitDiag (Loc, diag::decl_new_witness_table_entry, reqNewWitnessTableEntry ());
2404
+ }
2405
+ }
2406
+ }
2407
+
2408
+ void swift::ide::api::SDKNodeDeclFunction::diagnose (SDKNode *Right) {
2409
+ SDKNodeDeclAbstractFunc::diagnose (Right);
2410
+ auto *R = dyn_cast<SDKNodeDeclFunction>(Right);
2411
+ if (!R)
2412
+ return ;
2413
+ auto Loc = R->getLoc ();
2414
+ if (getSelfAccessKind () != R->getSelfAccessKind ()) {
2415
+ emitDiag (Loc, diag::func_self_access_change, getSelfAccessKind (),
2416
+ R->getSelfAccessKind ());
2417
+ }
2418
+ if (Ctx.checkingABI ()) {
2419
+ if (hasFixedBinaryOrder () != R->hasFixedBinaryOrder ()) {
2420
+ emitDiag (Loc, diag::func_has_fixed_order_change, hasFixedBinaryOrder ());
2421
+ }
2422
+ }
2423
+ }
2424
+
2425
+ static StringRef getAttrName (DeclAttrKind Kind) {
2426
+ switch (Kind) {
2427
+ #define DECL_ATTR (NAME, CLASS, ...) \
2428
+ case DAK_##CLASS: \
2429
+ return DeclAttribute::isDeclModifier (DAK_##CLASS) ? #NAME : " @" #NAME;
2430
+ #include " swift/AST/Attr.def"
2431
+ case DAK_Count:
2432
+ llvm_unreachable (" unrecognized attribute kind." );
2433
+ }
2434
+ llvm_unreachable (" covered switch" );
2435
+ }
2436
+
2437
+ static bool shouldDiagnoseAddingAttribute (SDKNodeDecl *D, DeclAttrKind Kind) {
2438
+ return true ;
2439
+ }
2440
+
2441
+ static bool shouldDiagnoseRemovingAttribute (SDKNodeDecl *D, DeclAttrKind Kind) {
2442
+ return true ;
2443
+ }
2444
+
2445
+ static bool isOwnershipEquivalent (ReferenceOwnership Left,
2446
+ ReferenceOwnership Right) {
2447
+ if (Left == Right)
2448
+ return true ;
2449
+ if (Left == ReferenceOwnership::Unowned && Right == ReferenceOwnership::Weak)
2450
+ return true ;
2451
+ if (Left == ReferenceOwnership::Weak && Right == ReferenceOwnership::Unowned)
2452
+ return true ;
2453
+ return false ;
2454
+ }
2455
+
2456
+ void swift::ide::api::detectRename (SDKNode *L, SDKNode *R) {
2457
+ if (L->getKind () == R->getKind () && isa<SDKNodeDecl>(L) &&
2458
+ L->getPrintedName () != R->getPrintedName ()) {
2459
+ L->annotate (NodeAnnotation::Rename);
2460
+ L->annotate (NodeAnnotation::RenameOldName, L->getPrintedName ());
2461
+ L->annotate (NodeAnnotation::RenameNewName, R->getPrintedName ());
2462
+ }
2463
+ }
2464
+
2465
+ void swift::ide::api::SDKNodeDecl::diagnose (SDKNode *Right) {
2466
+ SDKNode::diagnose (Right);
2467
+ auto *RD = dyn_cast<SDKNodeDecl>(Right);
2468
+ if (!RD)
2469
+ return ;
2470
+ detectRename (this , RD);
2471
+ auto Loc = RD->getLoc ();
2472
+ if (isOpen () && !RD->isOpen ()) {
2473
+ emitDiag (Loc, diag::no_longer_open);
2474
+ }
2475
+
2476
+ // Diagnose static attribute change.
2477
+ if (isStatic () ^ RD->isStatic ()) {
2478
+ emitDiag (Loc, diag::decl_new_attr, Ctx.buffer (isStatic () ? " not static" :
2479
+ " static" ));
2480
+ }
2481
+
2482
+ // Diagnose ownership change.
2483
+ if (!isOwnershipEquivalent (getReferenceOwnership (),
2484
+ RD->getReferenceOwnership ())) {
2485
+ auto getOwnershipDescription = [&](swift::ReferenceOwnership O) {
2486
+ if (O == ReferenceOwnership::Strong)
2487
+ return Ctx.buffer (" strong" );
2488
+ return keywordOf (O);
2489
+ };
2490
+ emitDiag (Loc, diag::decl_attr_change,
2491
+ getOwnershipDescription (getReferenceOwnership ()),
2492
+ getOwnershipDescription (RD->getReferenceOwnership ()));
2493
+ }
2494
+ // Diagnose generic signature change
2495
+ if (getGenericSignature () != RD->getGenericSignature ()) {
2496
+ // Prefer sugared signature in diagnostics to be more user-friendly.
2497
+ if (Ctx.commonVersionAtLeast (2 ) &&
2498
+ getSugaredGenericSignature () != RD->getSugaredGenericSignature ()) {
2499
+ emitDiag (Loc, diag::generic_sig_change,
2500
+ getSugaredGenericSignature (), RD->getSugaredGenericSignature ());
2501
+ } else {
2502
+ emitDiag (Loc, diag::generic_sig_change,
2503
+ getGenericSignature (), RD->getGenericSignature ());
2504
+ }
2505
+ }
2506
+
2507
+ // ObjC name changes are considered breakage
2508
+ if (getObjCName () != RD->getObjCName ()) {
2509
+ if (Ctx.commonVersionAtLeast (4 )) {
2510
+ emitDiag (Loc, diag::objc_name_change, getObjCName (), RD->getObjCName ());
2511
+ }
2512
+ }
2513
+
2514
+ if (isOptional () != RD->isOptional ()) {
2515
+ if (Ctx.checkingABI ()) {
2516
+ // Both adding/removing optional is ABI-breaking.
2517
+ emitDiag (Loc, diag::optional_req_changed, isOptional ());
2518
+ } else if (isOptional ()) {
2519
+ // Removing optional is source-breaking.
2520
+ emitDiag (Loc, diag::optional_req_changed, isOptional ());
2521
+ }
2522
+ }
2523
+
2524
+ // Diagnose removing attributes.
2525
+ for (auto Kind: getDeclAttributes ()) {
2526
+ if (!RD->hasDeclAttribute (Kind)) {
2527
+ if ((Ctx.checkingABI () ? DeclAttribute::isRemovingBreakingABI (Kind) :
2528
+ DeclAttribute::isRemovingBreakingAPI (Kind)) &&
2529
+ shouldDiagnoseRemovingAttribute (this , Kind)) {
2530
+ emitDiag (Loc, diag::decl_new_attr,
2531
+ Ctx.buffer ((llvm::Twine (" without " ) + getAttrName (Kind)).str ()));
2532
+ }
2533
+ }
2534
+ }
2535
+
2536
+ // Diagnose adding attributes.
2537
+ for (auto Kind: RD->getDeclAttributes ()) {
2538
+ if (!hasDeclAttribute (Kind)) {
2539
+ if ((Ctx.checkingABI () ? DeclAttribute::isAddingBreakingABI (Kind) :
2540
+ DeclAttribute::isAddingBreakingAPI (Kind)) &&
2541
+ shouldDiagnoseAddingAttribute (this , Kind)) {
2542
+ emitDiag (Loc, diag::decl_new_attr,
2543
+ Ctx.buffer ((llvm::Twine (" with " ) + getAttrName (Kind)).str ()));
2544
+ }
2545
+ }
2546
+ }
2547
+
2548
+ if (Ctx.checkingABI ()) {
2549
+ if (hasFixedBinaryOrder () && RD->hasFixedBinaryOrder () &&
2550
+ getFixedBinaryOrder () != RD->getFixedBinaryOrder ()) {
2551
+ emitDiag (Loc, diag::decl_reorder, getFixedBinaryOrder (),
2552
+ RD->getFixedBinaryOrder ());
2553
+ }
2554
+ }
2555
+ }
2556
+
2557
+ void swift::ide::api::SDKNodeDeclOperator::diagnose (SDKNode *Right) {
2558
+ SDKNodeDecl::diagnose (Right);
2559
+ auto *RO = dyn_cast<SDKNodeDeclOperator>(Right);
2560
+ if (!RO)
2561
+ return ;
2562
+ auto Loc = RO->getLoc ();
2563
+ if (getDeclKind () != RO->getDeclKind ()) {
2564
+ emitDiag (Loc, diag::decl_kind_changed, getDeclKindStr (RO->getDeclKind (),
2565
+ getSDKContext ().getOpts ().CompilerStyle ));
2566
+ }
2567
+ }
2568
+
2569
+ void swift::ide::api::SDKNodeDeclVar::diagnose (SDKNode *Right) {
2570
+ SDKNodeDecl::diagnose (Right);
2571
+ auto *RV = dyn_cast<SDKNodeDeclVar>(Right);
2572
+ if (!RV)
2573
+ return ;
2574
+ auto Loc = RV->getLoc ();
2575
+ if (Ctx.checkingABI ()) {
2576
+ if (hasFixedBinaryOrder () != RV->hasFixedBinaryOrder ()) {
2577
+ emitDiag (Loc, diag::var_has_fixed_order_change, hasFixedBinaryOrder ());
2578
+ }
2579
+ }
2580
+ }
2581
+
2582
+ static bool shouldDiagnoseType (SDKNodeType *T) {
2583
+ return T->isTopLevelType ();
2584
+ }
2585
+
2586
+ void swift::ide::api::SDKNodeType::diagnose (SDKNode *Right) {
2587
+ SDKNode::diagnose (Right);
2588
+ auto *RT = dyn_cast<SDKNodeType>(Right);
2589
+ if (!RT || !shouldDiagnoseType (this ))
2590
+ return ;
2591
+ assert (isTopLevelType ());
2592
+
2593
+ // Diagnose type witness changes when diagnosing ABI breakages.
2594
+ if (auto *Wit = dyn_cast<SDKNodeTypeWitness>(getParent ())) {
2595
+ auto *Conform = Wit->getParent ()->getAs <SDKNodeConformance>();
2596
+ if (Ctx.checkingABI () && getPrintedName () != RT->getPrintedName ()) {
2597
+ auto *LD = Conform->getNominalTypeDecl ();
2598
+ LD->emitDiag (SourceLoc (), diag::type_witness_change,
2599
+ Wit->getWitnessedTypeName (),
2600
+ getPrintedName (), RT->getPrintedName ());
2601
+ }
2602
+ return ;
2603
+ }
2604
+
2605
+ StringRef Descriptor = getTypeRoleDescription ();
2606
+ assert (isa<SDKNodeDecl>(getParent ()));
2607
+ auto LParent = cast<SDKNodeDecl>(getParent ());
2608
+ assert (LParent->getKind () == RT->getParent ()->getAs <SDKNodeDecl>()->getKind ());
2609
+ auto Loc = RT->getParent ()->getAs <SDKNodeDecl>()->getLoc ();
2610
+ if (getPrintedName () != RT->getPrintedName ()) {
2611
+ LParent->emitDiag (Loc, diag::decl_type_change,
2612
+ Descriptor, getPrintedName (), RT->getPrintedName ());
2613
+ }
2614
+
2615
+ if (hasDefaultArgument () && !RT->hasDefaultArgument ()) {
2616
+ LParent->emitDiag (Loc, diag::default_arg_removed, Descriptor);
2617
+ }
2618
+ if (getParamValueOwnership () != RT->getParamValueOwnership ()) {
2619
+ LParent->emitDiag (Loc, diag::param_ownership_change,
2620
+ getTypeRoleDescription (),
2621
+ getParamValueOwnership (),
2622
+ RT->getParamValueOwnership ());
2623
+ }
2624
+ }
2625
+
2626
+ void swift::ide::api::SDKNodeTypeFunc::diagnose (SDKNode *Right) {
2627
+ SDKNodeType::diagnose (Right);
2628
+ auto *RT = dyn_cast<SDKNodeTypeFunc>(Right);
2629
+ if (!RT || !shouldDiagnoseType (this ))
2630
+ return ;
2631
+ assert (isTopLevelType ());
2632
+ auto Loc = RT->getParent ()->getAs <SDKNodeDecl>()->getLoc ();
2633
+ if (Ctx.checkingABI () && isEscaping () != RT->isEscaping ()) {
2634
+ getParent ()->getAs <SDKNodeDecl>()->emitDiag (Loc,
2635
+ diag::func_type_escaping_changed,
2636
+ getTypeRoleDescription (),
2637
+ isEscaping ());
2638
+ }
2639
+ }
0 commit comments