diff options
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 23458c94a..f0cd32e74 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -353,6 +353,8 @@ struct SemanticsDeclHeaderVisitor : public SemanticsDeclVisitorBase, void checkDifferentiableCallableCommon(CallableDecl* decl); + void checkInterfaceRequirement(Decl* decl); + void checkCallableDeclCommon(CallableDecl* decl); void visitFuncDecl(FuncDecl* funcDecl); @@ -7800,11 +7802,84 @@ void SemanticsVisitor::checkAggTypeConformance(AggTypeDecl* decl) innerMember, Diagnostics::overrideModifierNotOverridingBaseDecl, innerMember); + + if (getShared()->isInLanguageServer() && + member->getName() == getShared()->getSession()->getCompletionRequestTokenName()) + { + // If we encountered a completion request for a decl name where an 'override' + // keyword is specified, we should suggest all the base decls that can be + // overridden, but have not been overridden yet. + // + calcOverridableCompletionCandidates(type, decl, member); + } } } } } + +void SemanticsVisitor::calcOverridableCompletionCandidates( + Type* aggType, + ContainerDecl* aggTypeDecl, + Decl* memberDecl) +{ + // We are in language server and the user requested to list + // all base interface methods that can be overrided in a conforming type. + // Collect all base interfaces methods that hasn't been overridden and + // suggest them as completion candidates. + if (as<InterfaceDecl>(aggTypeDecl)) + { + // If the aggType is an interface, we don't have any base methods to suggest. + return; + } + auto inheritanceInfo = getShared()->getInheritanceInfo(aggType); + HashSet<Decl*> overridenDecls; + for (auto member : aggTypeDecl->getMembers()) + { + member = maybeGetInner(member); + if (!as<FuncDecl>(member)) + continue; + if (auto overridedDeclModifier = member->findModifier<IsOverridingModifier>()) + { + overridenDecls.add(overridedDeclModifier->overridedDecl); + } + } + auto& contentAssistInfo = getShared()->getLinkage()->contentAssistInfo; + contentAssistInfo.completionSuggestions.scopeKind = CompletionSuggestions::ScopeKind::Decl; + auto varDeclBase = as<VarDeclBase>(memberDecl); + contentAssistInfo.completionSuggestions.formatMode = + varDeclBase ? CompletionSuggestions::FormatMode::FuncSignatureWithoutReturnType + : CompletionSuggestions::FormatMode::FullSignature; + + List<LookupResultItem> candidateItems; + for (auto facet : inheritanceInfo.facets) + { + // Extensions don't contribute overridable members. + if (facet->kind == Facet::Kind::Extension) + continue; + + auto interfaceDecl = facet->getDeclRef().as<InterfaceDecl>(); + if (!interfaceDecl) + continue; + for (auto requirement : interfaceDecl.getDecl()->getMembers()) + { + requirement = maybeGetInner(requirement); + if (!as<FuncDecl>(requirement)) + continue; + if (!overridenDecls.contains(requirement)) + { + auto requirementDeclRef = DeclRef<Decl>(requirement); + requirementDeclRef = + createDefaultSubstitutionsIfNeeded(m_astBuilder, this, requirementDeclRef); + candidateItems.add(LookupResultItem(requirementDeclRef)); + } + } + } + // Insert overridable candidates at the front of the list, so they are preferred over + // the completion results from checking ordinary type exprs. + contentAssistInfo.completionSuggestions.candidateItems.insertRange(0, candidateItems); +} + void SemanticsDeclBasesVisitor::_validateCrossModuleInheritance( AggTypeDeclBase* decl, InheritanceDecl* inheritanceDecl) @@ -10209,6 +10284,26 @@ void SemanticsDeclHeaderVisitor::checkDifferentiableCallableCommon(CallableDecl* } } +void SemanticsDeclHeaderVisitor::checkInterfaceRequirement(Decl* decl) +{ + if (isInterfaceRequirement(decl)) + { + if (auto funcBase = as<FunctionDeclBase>(decl)) + { + if (!as<FuncDecl>(decl) && funcBase->body != nullptr) + { + getSink()->diagnose(decl, Diagnostics::nonMethodInterfaceRequirementCannotHaveBody); + return; + } + } + // Interface requirement cannot be `override`. + if (decl->hasModifier<OverrideModifier>()) + { + getSink()->diagnose(decl, Diagnostics::interfaceRequirementCannotBeOverride); + } + } +} + void SemanticsDeclHeaderVisitor::checkCallableDeclCommon(CallableDecl* decl) { for (auto paramDecl : decl->getParameters()) @@ -10238,6 +10333,7 @@ void SemanticsDeclHeaderVisitor::checkCallableDeclCommon(CallableDecl* decl) } } + checkInterfaceRequirement(decl); checkVisibility(decl); } @@ -10642,7 +10738,10 @@ void SemanticsDeclHeaderVisitor::visitAbstractStorageDeclCommon(ContainerDecl* d // bool anyAccessors = decl->getMembersOfType<AccessorDecl>().isNonEmpty(); - + for (auto accessor : decl->getMembersOfType<AccessorDecl>()) + { + checkInterfaceRequirement(accessor); + } if (!anyAccessors) { GetterDecl* getterDecl = m_astBuilder->create<GetterDecl>(); |
