Skip to content

Support for autocompletion rules in FormRequest #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/completion/Registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ export default class Registry implements vscode.CompletionItemProvider {
);
};

const hasClassExtends = (classExtends: FeatureTagParam["classExtends"]) => {
if (typeof classExtends === "undefined" || classExtends === null) {
return true;
}

return parseResult.isClassDefinitionExtends(classExtends);
};

const hasMethodDefinition = (methodDefinitions: FeatureTagParam["methodDefinition"]) => {
if (typeof methodDefinitions === "undefined" || methodDefinitions === null) {
return true;
}

return parseResult.isMethodDefinition(methodDefinitions);
};

const isArgumentIndex = (
argumentIndex: number | number[] | undefined,
) => {
Expand Down Expand Up @@ -118,7 +134,9 @@ export default class Registry implements vscode.CompletionItemProvider {
hasClass(tag.class) &&
hasFunc(tag.method) &&
isArgumentIndex(tag.argumentIndex) &&
isNamedArg(tag.argumentName),
isNamedArg(tag.argumentName) &&
hasClassExtends(tag.classExtends) &&
hasMethodDefinition(tag.methodDefinition),
);
}) || null
);
Expand Down
21 changes: 17 additions & 4 deletions src/completion/Validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ export default class Validation implements CompletionProvider {
argumentIndex: 0,
},
{
classExtends: "Illuminate\\Foundation\\Http\\FormRequest",
classExtends: [
"Illuminate\\Foundation\\Http\\FormRequest",
"Livewire\\Form",
],
methodDefinition: "rules",
},
];
Expand All @@ -144,9 +147,7 @@ export default class Validation implements CompletionProvider {
return this.validatorValidation(document, position, result) || [];
}

// TODO: Deal with FormRequest@rules method

return [];
return this.handleFormRequestRulesMethod(document, position, result);
}

private handleValidateMethod(
Expand Down Expand Up @@ -182,6 +183,18 @@ export default class Validation implements CompletionProvider {
}
}

private handleFormRequestRulesMethod(
document: vscode.TextDocument,
position: vscode.Position,
result: AutocompleteResult,
): vscode.CompletionItem[] {
if (result.fillingInArrayKey()) {
return [];
}

return this.getRules(document, position);
}

private getRules(
document: vscode.TextDocument,
position: vscode.Position,
Expand Down
2 changes: 1 addition & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ interface FeatureTagParam {
argumentName?: string | string[];
classDefinition?: string;
methodDefinition?: string;
classExtends?: string;
classExtends?: string | string[];
classImplements?: string;
argumentIndex?: number | number[];
}
Expand Down
48 changes: 48 additions & 0 deletions src/parser/AutocompleteResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ export default class AutocompleteResult {
}

public fillingInArrayKey(): boolean {
if (this.result.type === "array") {
// I'm not sure if this is enough to determine
// if we're filling in a rules array key but I don't
// have better idea at this moment :/
return this.result.parent?.type !== "array_item"
&& this.result.autocompletingKey;
}

return this.param()?.autocompletingKey ?? false;
}

Expand Down Expand Up @@ -65,6 +73,46 @@ export default class AutocompleteResult {
);
}

public isClassDefinitionExtends(classNames: string | string[]) {
classNames = Array.isArray(classNames) ? classNames : [classNames];

let check = false;

this.loop((context) => {
if (classNames.some((className: string) => {
return (context as AutocompleteParsingResult.ClassDefinition).extends === className;
})) {
check = true;

return false;
}

return true;
});

return check;
}

public isMethodDefinition(methodNames: string | string[]) {
methodNames = Array.isArray(methodNames) ? methodNames : [methodNames];

let check = false;

this.loop((context) => {
if (methodNames.some((methodName: string) => {
return (context as AutocompleteParsingResult.MethodDefinition).methodName === methodName;
})) {
check = true;

return false;
}

return true;
});

return check;
}

public func() {
// @ts-ignore
return this.result.methodName ?? null;
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export namespace AutocompleteParsingResult {
type: "array";
parent: ContextValue | null;
children: ArrayItem[];
autocompletingKey: boolean;
}

export interface Assignment {
Expand Down