📜 ⬆️ ⬇️

Creating language extensions in RASE. Part 1. Language Intentions

image There is a deep-rooted opinion that language extensions are something like aerobatics in programming. The number of publications on this topic is constantly growing, but the share of Russian speakers among them, for obvious reasons, is negligible. The purpose of this series of articles is to show simple and effective ways to automate common daily tasks using the functionality for language extensions available in development environments based on Jetbrains MPS.

In our case, this environment will be the Realaxy ActionScript Editor, a beta version of which can be downloaded here . However, everything described below, with a few irrelevant details, is also applicable to writing language extensions for Java in the MPS editor.

Where to begin?


The simplest and most accessible application of the potential of the platform, specially tailored for the development of subject languages, will be the creation in it of a context extension using the example of working with strings. Our trial extension will solve the problem of “smart” screening of different quotes in cases like this:
')


The string contains single and double quotes. Our learning language extension will, depending on the context, have to offer escaping characters that cause conflict (escaping double quotes will be appropriate only for those lines that are framed by single quotes, and vice versa). Such a demonstration problem is good because it can be solved in a variety of ways, from writing simple automation scripts to using a plug-in architecture. In this article, it will be solved using Intentions , one of the aspects of language extensions in MPS.

What are Intentions?


The Intentions menu is one of the most commonly used functions of any editor based on IDEA. This is a simple and fast context-sensitive access to the most requested operations applicable to the syntax of the language (for example, “ Add Exeption ”, “ Invert If Condition ” or “ Convert Variable to Field ”). The availability of the Intentions menu is indicated by a light bulb icon appearing to the left of the line.



In our daily work, we are constantly confronted with similar functionality, since in one form or another it is present by default in all modern IDEs. In RASE (as in MPS or IDEA, by the way), the list of available Intentions for the current position is easiest to call up with the Alt-Enter keyboard shortcut .

For more information about their nature can be found in the official documentation on the site Jetbrains MPS.



Moving from words to deeds


1. First we create a new project. In the function Main () we place two strings, one will be framed with single quotes, and the other - double.



2. The editor has several viewing modes. The ActionScript View , which is offered to us by default, looks relatively ascetic and allows the developer to focus directly on the AS. In MPS View , which came to the editor "inherited" from the platform of the same name, a much larger number of possibilities is revealed (in particular, for writing language extensions).



3. Next, in the context menu of the project (opening on the right mouse click) add a new language:



4. Enter the language name ( myLanguages.escapedStrings ) and click on OK.



5. After these actions, a language called myLanguages.escapedStrings successfully appears in a new root in our project. You can see that myLanguages.escapedStrings already contains some so-called aspects (in the screenshot: structure , editor , constrains , typesystem , etc.). Later we will explain in detail how to use them.



6. Using the keyboard shortcut Alt-Enter or from the context menu of the language myLanguages.escapedStrings, we open the dialog box Language Properties .



7. In the window that opens, in the Dependencies tab in the Extended languages field, select com.realaxy.actionScript , and then click OK . This means that we will create this learning language extension for ActionScript.



8. Add the Intentions aspect. Intention is a kind of automatic script that performs a specific action on the selected language element (in our case, escaping quotes in String Literal ).



9. Create an intention declaration .



10. Name it EscapeQuotes and bind it to the StringLiteral . Then in the descriprion block we write the string “Escape Quotes”



11. The key is coming. In place of the isApplicable design , we must place a condition to which our Intention will correspond. To do this, we do not need special tricks: we work in an open source environment, and we just have to see how the mechanism for highlighting errors and warnings works in the editor. Our goal is not to reinvent the wheel, but to use the code that is already working safely. Let's digress a little and think about where it can be peeped? To do this, we turn to the error that we are going to fix. Let us move the cursor to our quoting string located in Main () to bring up the context menu.



12. Using the context menu or using the Shift-Ctrl-T keyboard shortcut ( Shift-Cmd-T on the Mac), we bring up the Show Type dialog box. It can rightfully be considered one of the most useful in AS-development, since almost all system messages (warnings, info and errors) somehow belong to the type system.



13. So, in the window that appears, we see information about what kind of object it is, what type it is and where it is in the type hierarchy. Click on the Go To Rule button which Caused Error (as can be seen from the previous screenshot, to save time, we could go directly to this IDE function). Go to the tab that appears and see the construction, from which we understand that the code we are interested in is most likely executed when isCorrect is called. Just how to get to him?



14. If you press the Ctrl (or Cmd ) key and hover the mouse over the name of the method, an underline will appear, reminding us of a hypertext link. Clicking on it, go to the starting point of the code. We need it.



15. Next, copy the code of the isCorrect method, go to the IntentionDeclaration tab and paste it into the isApplicable method to simplify and modify the condition for our needs:



16. Now it's time to add the code that will be executed when we call our Intention . In the execute method we write the modification of our node. value



17. Stop Why don't we use regular expressions for more convenience? No sooner said than done. Using the Ctrl-L combination ( Cmd-L on Mac), import the language regexp .



18. As a result, we obtain the following construction ...



19. ... in which it remains only to insert the appropriate regexp.



The entire declaration of Intention is as follows:



20. Finally, Intention can be compiled. Press Ctrl-F9 (on the Mac - Cmd-F9 ) or select Build> Make Module (s) in the main menu, then go to Main () , try to launch our language extension by pressing Alt-Enter on the line containing the error ... and notice that nothing happens. What is the matter?



21. It's simple: we compiled the language extension, but did not import it into the project. By the familiar combination of Ctrl-L ( Cmd-L on Mac), we correct this misunderstanding.



22. Again, click on our "faulty" line combination Alt-Enter .



23. And we get the desired result.



24. What to do next - a matter of taste. While our extension works only with strings enclosed in double quotes. Since we want to quickly make it applicable also to single quotes, the easiest way is to simply duplicate our declaration Intention Escape Quotes with Ctrl-D ( Cmd-D ) and change only the data type, name and quotation mark in it where it is need to.



25. Slightly adapt our code:



Of course, it was possible to achieve greater compactness of the code and get along, for example, with one root instead of two for each of the quotes. However, do not forget that the main goal was to get a quick and effective automation of routine action, and in our case this problem was solved simply and elegantly.
26. Mission accomplished. After recompiling the root using Ctrl-F9 (on Mac - Cmd + F9 ), we get a ready script for escaping quotes. Here is the result of his work:




Instead of conclusion


As you can see, automating daily tasks in Jetbrains MPS-based editors is a snap. The resulting solution can be easily transferred to other projects, adding our language extension to their properties.



The functionality described in this article is only the first step into the world of LOP and DSL. Nevertheless, the Intentions language alone is abundantly enough for the developer to organize his own production infrastructure “here and now” for his tasks.

Those readers who are not going to stop there and would like to get into the practice of creating language extensions in more detail, we advise to follow the updates. In the next article, the same problem will be solved in a different way, with more extensive use of various linguistic aspects.

Link to project sources .

Special thanks to Evgeny Potapenko ( potapenko ) for all-round help and support in writing this material.

Source: https://habr.com/ru/post/122358/


All Articles