Skip to content

Commit

Permalink
Merge branch 'main' into upgrade/deps-july-2024-2
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Jul 23, 2024
2 parents 5485626 + 96c81c5 commit bef3473
Show file tree
Hide file tree
Showing 3 changed files with 474 additions and 246 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
changeKind: feature
packages:
- "@typespec/compiler"
---

Support completion for template parameter extending model or object value

Example
```tsp
model User<T extends {name: string, age: int16}> {
}
alias user = User< {┆
| [age]
| [name]
```
43 changes: 35 additions & 8 deletions packages/compiler/src/core/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2837,7 +2837,14 @@ export function createChecker(program: Program): Checker {
node: TemplateArgumentNode,
mapper: TypeMapper | undefined
) {
const resolved = resolveTypeReferenceSym(node.parent as TypeReferenceNode, mapper, false);
const ref = node.parent as TypeReferenceNode;
let resolved = resolveTypeReferenceSym(ref, mapper, false);
// if the reference type can't be resolved and has parse error,
// it likely means the reference type hasn't been completed yet. i.e. Foo<string,
// so try to resolve it by it's target directly to see if we can find its sym
if (!resolved && hasParseError(ref) && ref.target !== undefined) {
resolved = resolveTypeReferenceSym(ref.target, mapper, false);
}
return (resolved?.declarations.filter((n) => isTemplatedNode(n)) ?? []) as TemplateableNode[];
}

Expand All @@ -2862,6 +2869,7 @@ export function createChecker(program: Program): Checker {
return (
(isModelOrArray(n) &&
(n.parent?.kind === SyntaxKind.TemplateParameterDeclaration ||
n.parent?.kind === SyntaxKind.TemplateArgument ||
n.parent?.kind === SyntaxKind.DecoratorExpression)) ||
(isModelOrArrayValue(n) &&
(n.parent?.kind === SyntaxKind.CallExpression ||
Expand All @@ -2872,6 +2880,7 @@ export function createChecker(program: Program): Checker {
let refType: Type | undefined;
switch (foundNode?.parent?.kind) {
case SyntaxKind.TemplateParameterDeclaration:
case SyntaxKind.TemplateArgument:
refType = getReferencedTypeFromTemplateDeclaration(foundNode as ModelOrArrayNode);
break;
case SyntaxKind.DecoratorExpression:
Expand Down Expand Up @@ -2939,27 +2948,45 @@ export function createChecker(program: Program): Checker {
return cur?.kind === "Model" ? cur : undefined;
}

function getReferencedTypeFromTemplateDeclaration(dftNode: ModelOrArrayNode): Type | undefined {
const templateParmaeterDeclNode = dftNode?.parent;
function getReferencedTypeFromTemplateDeclaration(node: ModelOrArrayNode): Type | undefined {
let templateParmaeterDeclNode: TemplateParameterDeclarationNode | undefined = undefined;
if (
node?.parent?.kind === SyntaxKind.TemplateArgument &&
node?.parent?.parent?.kind === SyntaxKind.TypeReference
) {
const argNode = node.parent;
const refNode = node.parent.parent;
const decl = getTemplateDeclarationsForArgument(
argNode,
// We should be giving the argument so the mapper here should be undefined
undefined /* mapper */
);

const index = refNode.arguments.findIndex((n) => n === argNode);
if (decl.length > 0 && decl[0].templateParameters.length > index) {
templateParmaeterDeclNode = decl[0].templateParameters[index];
}
} else if (node.parent?.kind === SyntaxKind.TemplateParameterDeclaration) {
templateParmaeterDeclNode = node?.parent;
}

if (
templateParmaeterDeclNode?.kind !== SyntaxKind.TemplateParameterDeclaration ||
!templateParmaeterDeclNode.constraint ||
!templateParmaeterDeclNode.default ||
templateParmaeterDeclNode.default !== dftNode
!templateParmaeterDeclNode.constraint
) {
return undefined;
}

let constraintType: Type | undefined;
if (
isModelOrArrayValue(dftNode) &&
isModelOrArrayValue(node) &&
templateParmaeterDeclNode.constraint.kind === SyntaxKind.ValueOfExpression
) {
constraintType = program.checker.getTypeForNode(
templateParmaeterDeclNode.constraint.target
);
} else if (
isModelOrArrayType(dftNode) &&
isModelOrArrayType(node) &&
templateParmaeterDeclNode.constraint.kind !== SyntaxKind.ValueOfExpression
) {
constraintType = program.checker.getTypeForNode(templateParmaeterDeclNode.constraint);
Expand Down
Loading

0 comments on commit bef3473

Please sign in to comment.