Angular Language Service for a Custom Language
This challenge asks you to build a simplified language service for a fictional programming language called "Spark." A language service enhances the developer experience in an IDE by providing features like autocompletion, error highlighting, and go-to-definition. Implementing a language service in Angular allows you to provide these benefits to developers working with Spark within an Angular application.
Problem Description
You need to create a basic Angular language service that provides autocompletion suggestions for the "Spark" language. Spark has a very simple syntax: it consists of variable declarations and assignments using the keyword let, and function calls using the keyword spark. Variable names are alphanumeric strings. Function names are also alphanumeric strings. Function calls can optionally include arguments, which are also alphanumeric strings separated by commas.
What needs to be achieved:
- Create an Angular service that accepts a string of Spark code as input.
- Parse the code to identify potential autocompletion locations (after
letand before the=) and function call locations (afterspark). - Provide a list of possible autocompletion suggestions based on the parsed code. Suggestions should be variable names or function names.
- The service should return an array of strings representing the autocompletion suggestions.
Key Requirements:
- The service must be injectable into an Angular component.
- The service must have a method
getCompletions(code: string): string[]that takes Spark code as input and returns an array of completion suggestions. - The parsing logic should be robust enough to handle basic syntax errors (e.g., missing
letorspark). While full error handling isn't required, the service shouldn't crash on invalid input. - The suggestions should be relevant to the context. For example, after
let, suggest variable names. Afterspark, suggest function names.
Expected Behavior:
Given a string of Spark code, the service should return an array of strings containing possible autocompletion suggestions. The suggestions should be based on the identified keywords and the existing code.
Edge Cases to Consider:
- Empty input string.
- Code with no
letorsparkkeywords. - Code with invalid syntax (e.g., missing semicolon, mismatched parentheses - although full syntax validation is not required).
- Multiple
letandsparkkeywords in the same input string.
Examples
Example 1:
Input: "let x = 10; let y = 20;"
Output: ["x", "y"]
Explanation: The code contains two `let` keywords. The service should suggest "x" after the first `let` and "y" after the second `let`.
Example 2:
Input: "spark greet(world);"
Output: ["greet"]
Explanation: The code contains a `spark` keyword. The service should suggest "greet" after the `spark`.
Example 3:
Input: "let a = 1; spark calculate(a, b);"
Output: ["a", "calculate"]
Explanation: The code contains both a `let` and a `spark` keyword. The service should suggest "a" after the `let` and "calculate" after the `spark`.
Example 4:
Input: ""
Output: []
Explanation: The input is an empty string. No suggestions are needed.
Constraints
- The Spark language is extremely simple, as described above. Do not attempt to implement a full-fledged parser.
- The service should be performant enough to provide suggestions in a reasonable amount of time (e.g., less than 100ms for typical code snippets). Optimization is not the primary focus, but avoid excessively inefficient algorithms.
- The code must be written in TypeScript and adhere to Angular coding standards.
- The service should be testable. Consider how you would test the service's functionality.
Notes
- You can use regular expressions to parse the Spark code, but be mindful of their limitations.
- Focus on providing a basic implementation that demonstrates the core concepts of a language service.
- Consider how you would extend this service to support more complex language features in the future.
- Think about how you would integrate this service with an Angular component to display the autocompletion suggestions to the user. (While you don't need to build the entire component, consider the interaction.)