Angular Custom Completion Provider for a Simple Language
This challenge asks you to build a custom completion provider for an Angular application. The provider will suggest code completions for a simplified language consisting of keywords and identifiers. This is a valuable exercise in understanding Angular's language service and how to extend it to support custom syntax.
Problem Description
You need to create an Angular completion provider that suggests completions for a simplified language called "SimpleLang." SimpleLang consists of the following keywords: begin, end, let, if, else, print. Additionally, the provider should suggest any valid identifier (a sequence of letters, numbers, and underscores, starting with a letter) that has already been declared in the current scope. For simplicity, assume that identifiers are declared when they are first used. The provider should not suggest keywords as identifiers, and vice versa.
The completion provider should be integrated into an Angular component that displays a text editor. As the user types in the editor, the provider should suggest relevant completions. The suggestions should be displayed in a dropdown list below the editor.
Key Requirements:
- Keyword Completion: Always suggest the defined keywords (
begin,end,let,if,else,print). - Identifier Completion: Suggest identifiers that have been previously used in the code.
- No Keyword/Identifier Confusion: Do not suggest keywords as identifiers, and do not suggest identifiers as keywords.
- Contextual Suggestions: The suggestions should be based on the current cursor position in the editor.
- Angular Integration: The provider must be properly integrated with Angular's language service.
Expected Behavior:
- When the user types, the provider should analyze the text before the cursor.
- Based on the text, the provider should generate a list of relevant completions.
- The completions should be displayed in a dropdown list.
- When the user selects a completion, it should be inserted at the cursor position.
Edge Cases to Consider:
- Empty editor content.
- Cursor position at the beginning of the editor.
- Cursor position after a keyword.
- Cursor position after an identifier.
- Multiple identifiers with the same prefix.
- Long input strings.
Examples
Example 1:
Input: "let "
Output: ["begin", "end", "if", "else", "print", "x", "y", "z"]
Explanation: The cursor is after "let ". The provider should suggest keywords and any previously declared identifiers (assuming x, y, and z have been declared).
Example 2:
Input: "if "
Output: ["begin", "end", "let", "else", "print", "x", "y", "z"]
Explanation: The cursor is after "if ". The provider should suggest keywords and previously declared identifiers.
Example 3:
Input: "x."
Output: ["y", "z"]
Explanation: The cursor is after "x.". The provider should suggest identifiers that start with "y" or "z" (assuming they have been declared).
Example 4:
Input: "begin"
Output: []
Explanation: The cursor is at the end of the keyword "begin". No further suggestions are needed.
Constraints
- Performance: The completion provider should respond quickly (within 200ms) even for long input strings. Avoid computationally expensive operations.
- Identifier Length: Identifiers are assumed to be reasonably short (maximum 32 characters).
- SimpleLang Syntax: Assume SimpleLang code is well-formed and doesn't contain complex syntax. Focus on the completion logic, not parsing.
- Angular Version: Assume Angular 16 or later.
Notes
- You'll need to create a custom
CompletionProviderclass that extendsLanguageServiceand implements theprovideCompletionItemsmethod. - Consider using a simple data structure (e.g., a
Set) to store declared identifiers. - The
triggerCompletionmethod in the component will be responsible for calling the completion provider. - Focus on the core completion logic. You don't need to implement a full-fledged editor with syntax highlighting or other advanced features.
- Think about how to efficiently filter the list of identifiers based on the current prefix.
- Use Angular's dependency injection to provide the completion provider to the component.