@@ -54,6 +54,16 @@ struct swift::ide::api::SDKNodeInitInfo {
5454 SDKNode* createSDKNode (SDKNodeKind Kind);
5555};
5656
57+ bool swift::ide::api::hasValidParentPtr (SDKNodeKind kind) {
58+ switch (kind) {
59+ case SDKNodeKind::Conformance:
60+ case SDKNodeKind::DeclAccessor:
61+ return false ;
62+ default :
63+ return true ;
64+ }
65+ }
66+
5767SDKContext::SDKContext (CheckerOptions Opts): Diags(SourceMgr), Opts(Opts) {}
5868
5969DiagnosticEngine &SDKContext::getDiags (SourceLoc Loc) {
@@ -109,6 +119,7 @@ SDKNodeDecl::SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind)
109119 IsOverriding(Info.IsOverriding),
110120 IsOpen(Info.IsOpen),
111121 IsInternal(Info.IsInternal), IsABIPlaceholder(Info.IsABIPlaceholder),
122+ IsFromExtension(Info.IsFromExtension),
112123 ReferenceOwnership(uint8_t (Info.ReferenceOwnership)),
113124 GenericSig(Info.GenericSig),
114125 SugaredGenericSig(Info.SugaredGenericSig),
@@ -826,6 +837,25 @@ static bool hasSameParameterFlags(const SDKNodeType *Left, const SDKNodeType *Ri
826837 return true ;
827838}
828839
840+ // Return whether a decl has been moved in/out to an extension
841+ static Optional<bool > isFromExtensionChanged (const SDKNode &L, const SDKNode &R) {
842+ assert (L.getKind () == R.getKind ());
843+ // Version 8 starts to include whether a decl is from an extension.
844+ if (L.getJsonFormatVersion () + R.getJsonFormatVersion () < 2 * 8 ) {
845+ return llvm::None;
846+ }
847+ auto *Left = dyn_cast<SDKNodeDecl>(&L);
848+ auto *Right = dyn_cast<SDKNodeDecl>(&R);
849+ if (!Left) {
850+ return llvm::None;
851+ }
852+ if (Left->isFromExtension () == Right->isFromExtension ()) {
853+ return llvm::None;
854+ } else {
855+ return Right->isFromExtension ();
856+ }
857+ }
858+
829859static bool isSDKNodeEqual (SDKContext &Ctx, const SDKNode &L, const SDKNode &R) {
830860 auto *LeftAlias = dyn_cast<SDKNodeTypeAlias>(&L);
831861 auto *RightAlias = dyn_cast<SDKNodeTypeAlias>(&R);
@@ -965,6 +995,8 @@ static bool isSDKNodeEqual(SDKContext &Ctx, const SDKNode &L, const SDKNode &R)
965995 case SDKNodeKind::TypeWitness:
966996 case SDKNodeKind::DeclImport:
967997 case SDKNodeKind::Root: {
998+ if (isFromExtensionChanged (L, R))
999+ return false ;
9681000 return L.getPrintedName () == R.getPrintedName () &&
9691001 L.hasSameChildren (R);
9701002 }
@@ -1376,6 +1408,13 @@ StringRef SDKContext::getInitKind(Decl *D) {
13761408 return StringRef ();
13771409}
13781410
1411+ static bool isDeclaredInExtension (Decl *D) {
1412+ if (auto *DC = D->getDeclContext ()->getAsDecl ()) {
1413+ return isa<ExtensionDecl>(DC);
1414+ }
1415+ return false ;
1416+ }
1417+
13791418SDKNodeInitInfo::SDKNodeInitInfo (SDKContext &Ctx, Decl *D):
13801419 Ctx(Ctx), DKind(D->getKind ()), Loc(D->getLoc ()),
13811420 Location(calculateLocation(Ctx, D)),
@@ -1394,6 +1433,7 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Decl *D):
13941433 IsImplicit(D->isImplicit ()),
13951434 IsDeprecated(D->getAttrs ().getDeprecated(D->getASTContext ())),
13961435 IsABIPlaceholder(isABIPlaceholderRecursive(D)),
1436+ IsFromExtension(isDeclaredInExtension(D)),
13971437 DeclAttrs(collectDeclAttributes(D)) {}
13981438
13991439SDKNodeInitInfo::SDKNodeInitInfo (SDKContext &Ctx, OperatorDecl *OD):
@@ -2040,6 +2080,7 @@ void SDKNodeDecl::jsonize(json::Output &out) {
20402080 uint8_t Raw = uint8_t (getReferenceOwnership ());
20412081 out.mapRequired (getKeyContent (Ctx, KeyKind::KK_ownership).data (), Raw);
20422082 }
2083+ output (out, KeyKind::KK_isFromExtension, IsFromExtension);
20432084}
20442085
20452086void SDKNodeDeclAbstractFunc::jsonize (json::Output &out) {
@@ -2611,6 +2652,23 @@ void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose(SDKNode *Right) {
26112652 if (reqNewWitnessTableEntry () != R->reqNewWitnessTableEntry ()) {
26122653 emitDiag (Loc, diag::decl_new_witness_table_entry, reqNewWitnessTableEntry ());
26132654 }
2655+
2656+ // Diagnose moving a non-final class member to an extension.
2657+ if (hasValidParentPtr (getKind ())) {
2658+ while (auto *parent = dyn_cast<SDKNodeDecl>(getParent ())) {
2659+ if (parent->getDeclKind () != DeclKind::Class) {
2660+ break ;
2661+ }
2662+ if (hasDeclAttribute (DeclAttrKind::DAK_Final)) {
2663+ break ;
2664+ }
2665+ auto result = isFromExtensionChanged (*this , *Right);
2666+ if (result.hasValue () && *result) {
2667+ emitDiag (Loc, diag::class_member_moved_to_extension);
2668+ }
2669+ break ;
2670+ }
2671+ }
26142672 }
26152673}
26162674
0 commit comments