summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp101
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>();