-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathplatform.html
1470 lines (1105 loc) · 71.6 KB
/
platform.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="utf-8">
<title>mbeddr - engineering the future of embedded software</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description"
content="The website of mbeddr, a set of integrated and extensible languages for embedded software engineering, plus an IDE with refatorings, a debugger and verification tools.">
<meta name="author" content="Markus Voelter">
<!-- styles -->
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="images/favicon.gif">
<link href="css/bootstrap.css" rel="stylesheet" type='text/css'>
<link href="css/bootstrap-responsive.css" rel="stylesheet" type='text/css'>
<link href="css/style.css" rel="stylesheet" type='text/css'>
<link href="css/shield-responsive.css" rel="stylesheet" type='text/css'>
<link href='css/fonts.css' rel='stylesheet' type='text/css'>
<link href="css/prettyPhoto.css" rel="stylesheet" media="screen" type='text/css'>
<link href="google-code-prettify/prettify.css" type="text/css" rel="stylesheet"/>
<!--[if lt IE 9]>
<link href="css/iebugs.css" rel="stylesheet" type='text/css'>
<![endif]-->
<script src="js/twitter.js" type="text/javascript"></script>
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/jquery.prettyPhoto.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$('a[data-rel]').each(function () {
$(this).attr('rel', $(this).data('rel'));
});
$("a[rel^='prettyPhoto']").prettyPhoto({
animation_speed: 'fast',
slideshow: 5000,
autoplay_slideshow: false,
opacity: 0.80,
show_title: true,
theme: 'ligh_square',
overlay_gallery: false,
social_tools: false
});
$('#nav-outline > li > a').live('click', function () {
$(this).parent().find('ul').slideToggle();
});
$('.has-popover').popover();
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
});
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
var pluginUrl = '//www.google-analytics.com/plugins/ga/inpage_linkid.js';
_gaq.push(['_require', 'inpage_linkid', pluginUrl]);
_gaq.push([ '_setAccount', 'UA-45406798-1' ]);
_gaq.push([ '_trackPageview' ]);
(function () {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'stats.g.doubleclick.net/dc.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-WZX646"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-WZX646');</script>
<!-- End Google Tag Manager -->
<!-- Navbar -->
<div class="navbar navbar-fixed-top"
style="border-bottom: 1px solid #000;">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="index.html"></a>
<div class="nav-collapse collapse" style="height: 0px;">
<ul class="nav">
<li><a href="/blog">News</a></li>
<li><a href="benefits.html">Benefits</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="platform.html">Platform</a></li>
<li><a href="learn.html">Learn</a></li>
<li><a href="faq.html">FAQ</a></li>
<li><a href="screencasts.html">Screencasts</a></li>
<li><a href="support.html">Support</a></li>
<li><a href="team.html">Team</a></li>
<li><a href="mps.html">MPS</a></li>
</ul>
</div>
<!--/.nav-collapse -->
<div class="btn-group pull-right">
<g:plusone href="http://mbeddr.com"></g:plusone>
</div>
</div>
</div>
</div>
<!-- Navbar End -->
<div id="header_wrapper" class="container">
</div>
<div id="page">
<div class="inner">
<div class="container clearfix">
<div class="container">
<div class="container">
<div class="span7">
<h2>Introduction</h2>
<p>
<b>What it is</b> The mbeddr.platform is a collection of utilities and MPS extensions useful
to many different kinds of systems built on MPS. We have developed it as part
of the development of mbeddr, and all the utilities and extensions mentioned
here are used extensively in mbeddr.
</p>
<p>
Some extensions work automatically as soon as you put the platform into your
plugins folder. We describe these first. Other extensions require some
simple code to be written as part of your language: typically, your language
concepts must implement an interface and implement one or two methods, or you
just use some new cell in the editor. We describe that second group next.
The final group are full blown additional languages, typically in the editor,
and require more work to understand and use. We describe these last.
</p>
<p>
<b>This Page</b> This documentation is intended as an overview to give you a head start.
All the examples we refer to are in mbeddr, so we suggest you download
mbeddr (not just the platform) as a means for you to see how the extensions
work. Here are some of the mechanisms we use in this documentation:
</p>
<ul>
<li>We briefly describe what each utility or extension does.
</li>
<li>We mention a qualified name of the a language concept. Open this concept
in mbeddr, and perform an Find Usages (Instances) to find example code
</li>
<li>We point to example code by using a Node Info (see below) or Node URL.
Check out this example code to understand how the extension works.
</li>
</ul>
<p>
Note that for historic reasons, the various extensions reside in various
repositories and languages including git repositories by Sascha Lisson,
languages and solutions in the com.mbeddr.mpsutil namespace as well as
in one monster langauage com.mbeddr.core.base (and its plugin solution).
If you download the platform, all of these are available, the platform
packages them together. Nonetheless, we will clean up the structure and
modularity of these things in the future -- for historic reasons, some
of them are in the wrong place.
</p>
<p>
If the explanations here plus the sample code is not enough,
<a href="http://mbeddr.com/support.html">contact the team and ask for help!</a>
</p>
<p>
<b>Download</b> Similar to <a href="/download.html">mbeddr as a whole</a> you can get the
platform from the repository, or you can download a distribution/binary
<a href="https://github.com/mbeddr/mbeddr.core/releases">from the github release page</a>;
each release has a download package specifically for the platform.
</p>
<br/>
<h2>Utilitities that just work</h2>
<h3>Console Opener (com.mbeddr.core.base)</h3>
<p>
In the context menu (in the project explorer) of solutions and models
you will find an Open Terminal entry. For a solution, it opens a terminal
in the solution's root folder. For a model, it opens the terminal in the
output folder (where the generated code resides).
</p>
<br/>
<br/><hr/>
<h3>Text Search (com.mbeddr.core.base)</h3>
<p>
On Models and Solutions there is a context menu entry Text Search. When
activated, it opens a tool on the right side of MPS where you can enter a
search term that is then full-text-searched in the respective solution or
model. By default, the searcher looks at names of concepts as well as richtext
paragraphs (see below). If you want your language concepts to contribute
more text to be searched, implement the ISearchSupport interface.
</p>
<br/>
<br/><hr/>
<h3>Node Info and URL (com.mbeddr.core.base)</h3>
<p>
The Edit menu as well as the context menu of a node contains an entry
Copy Node URL. This creates a http URL for the current node that encodes
the model name the unique node ID.
</p>
<p>
<a href="http://localhost:8080/select/tutorial/r:0d2d1e96-2ec7-4797-ad03-f95f261d35d7/3978189422528365848/">http://localhost:8080/select/tutorial/r:0d2d1e96-2ec7-4797-ad03-f95f261d35d7/3978189422528365848/</a>
</p>
<p>
This URL can be pasted into text editors or moved around by email.
Clicking on the node will select the respective node in the MPS editor. Note
that this only works if the respective project is already open. The Edit
menu also contains an entry Copy Node Info, which creates a human readable
"path" to the current node, plus the URL:
</p>
<p>
<pre>project: tutorial (/Users/markusvoelter/Documents/mbeddr/mbeddr.core/code/applications/tutorial)
module: mbeddr.tutorial.main
model: mbeddr.tutorial.main.analyses
node: BasicAnalyses [CBMCAnalysisConfiguration] (root)
url: http://localhost:8080/select/tutorial/r:0d2d1e96-2ec7-4797-ad03-f95f261d35d7/3978189422528365848/</pre>
</p>
<p>
Finally, the URL can also be changed by replacing the "select" part with
"content". This will return an XML representation of the node that can be
pasted into a textual environment (see below).
</p>
<br/><hr/>
<h3>Copy/Paste to XML (com.mbeddr.core.base)</h3>
<p>
A node can be copied to an XML representation using the Edit menu. This XML
can then be passed around in text-oriented tools. There is also a Paste from
XML entry in the Edit menu which recreates an MPS node from the XML
representation. This works generically for nodes of any language. Note
that the XML format is the same as returned from the URL/content thing
mentioned above.
</p>
<br/><hr/>
<h3>Unique Names (com.mbeddr.mpsutil.uniquenames)</h3>
<p>
MPS references all nodes by their id, not their name. Still, as humans, we see
only the name, and this might be ambiguous. The Unique Names hint can be activated
in MPS Preferences, Editor Hints. It shows as much of the full qualified name as
required to render a name unique.
</p>
<p>
Example Concept:
<br/><img src="/images/blog/uniquenames_concept_plain.png"/>
<br/>
<br/><img src="/images/blog/uniquenames_concept_unique.png"/>
</p>
<p>
Example BaseLanguage:
<br/><img src="/images/blog/uniquenames_class_plain.png"/>
<br/>
<br/><img src="/images/blog/uniquenames_class_unique.png"/>
</p>
<br/><hr/>
<h3>Generated Artifacts Reviewer</h3>
<p>
In the context menu of the editor you will find an
Generated Artifacts Review -> Open Review Tool entry. This
will open a MPS tool where you can select one of the generated files.
Simply clicking on a line of the text-area containing the generated file will jump to
the DSL node from which this line was generated. The functionality is
generic and can be used for each high level DSL (e.g. from mbeddr or MPS itself) and
generated artifacts(e.g. C code, Makefiles, Java code).
</p>
<p>
Example 1: Side-by-side mbeddr DSLs and Generated C Code (also check this <a href="https://www.youtube.com/watch?v=xLUb4HQY_f0">video</a>):
<br/><img src="images/generated_code_review_from_mbeddr.png"/>
<br/><br/>
</p>
<p>
Example 2: Side-by-side MPS DSLs and Generated Java Code:
<br/><img src="images/generated_code_review_from_mps_generators_dsls.png"/>
<br/><br/>
</p>
<br/>
<h2>Simple Extensions</h2>
<h3>Context Actions (com.mbeddr.mpsutil.contextactions)</h3>
<p>
MPS supports the use of non-textual notations as a consequence of its projectional
editor. This means that programs may contain notations that cannot be typed in the
same way as they look on the screen. Examples include sum symbols or fraction
bars. Currently these are entered using textual aliases such as sum or frac.
</p>
<p>
However, this is not easily explorable: users cannot easily find out which
such "hidden" aliases are available in a given context.
</p>
<p>
To solve this issue, we have created the context actions. These look like a
palette in a graphical editor. Depending on the user's selection (cursor
position), the context actions shows what is available for the user to do.
Context actions can include
</p>
<p>
<ul>
<li>Code completion menu entries</li>
<li>Intentions</li>
<li>Left and Right Transformations</li>
<li>Refactorings</li>
<li>Existing UI-actions</li>
<li>... as well as arbitrary, directly inserted code.</li>
</ul>
</p>
<br/>
<img src="/images/blog/contextActions.png"/>
<br/><br/>
<p>
The context actions language ships with a DSL that supports the convenient deployment of the above mentioned
artifacts into the context action palette.
</p>
<h3>Custom Project Views (com.mbeddr.mpsutil.projectview)</h3>
<p>
For many applications (and their end users) the default MPS Project Explorer
(aka Logical View) is too complicated -- it shows too much "unnecessary" stuff.
Also, depending on the use case and the stakeholder, the structure of the primary
navigation device must be different, adapted for the use case or stakeholder.
</p>
<p>
The platform contains a DSL to describe the structure of arbitrary alternative
tree views in the project explorer; MPS already provides a drop down menu to select
from various views, and the DSL can contribute additional ones.
</p>
<p>
The DSL supports the definition of arbitrary structures, labels, icons and actions,
and also lets you add additional nodes useful for structuring the tree. To see how
this DSL works, checkout the custom views defined in <i>com.mbeddr.mpsutil.projectview.views</i>
solution as well as our new Favourites view in the <i>com.mbeddr.mpsutil.favourites.plugin</i>
plugin solution. Below is a screenshot of that favourites view.
</p>
<center>
<img src="/images/favourites.png"/>
</center>
<br/>
<br/><hr/>
<h3>Serializer (com.mbeddr.mpsutil.serializer)</h3>
<p>
The serializer used to create the XML representations above is accessible
programmatically. The classes are called <a href="http://localhost:8080/select/tutorial/r:5bc020f2-590a-4818-ae68-fa483b92486f/98682967484619562/">NodeSerializer</a> and
<a href="http://localhost:8080/select/tutorial/r:5bc020f2-590a-4818-ae68-fa483b92486f/98682967488267255/">NodeDeserializer</a>
</p>
<br/>
<br/><hr/>
<h3>Boolean Editor (de.itemis.mps.editor.bool)</h3>
<p>
Additional editor cells are available to represent Boolean values in the
editor with a representation other than "true" and "false". The bool{} cell
can be configured with arbitrary strings for the true and false case (such
as "yes" and "no" or "on" and "off"). The checkbox{} cell renders an actual
checkbox (with a little cross in it).
</p>
<br/>
<br/><hr/>
<h3>Date Picker (com.mbeddr.mpsutil.datepicker)</h3>
<p>
A classic widget to select a date from a pop-up calendar.
</p>
<br/>
<img src="/images/datepicker.png"/>
<br/>
<p>
This is only the control, i.e. the developer is responsible for synchronizing the control
with the source of the shown date. We provide hooks executed before showing the calendar,
for determining whether a date is valid, and to process a selected date.
</p>
<br/>
<br/><hr/>
<h3>Tooltips (de.itemis.mps.tooltips)</h3>
<p>
Sascha has added support for tooltips to MPS. Tooltips
are defined using the regular MPS projectional editor and hence have all its notational flexibility. Check out the
video below:
</p>
<br/>
<a href="https://www.youtube.com/watch?v=FTvUhjK8Zwk"><img src="/images/blog/tooltips.png"/></a><br/>
<br/>
<p>
To use it, just use the language mentioned above and include a tooltip cell in the editor:
in the top slot of the cell put the original editor. In the bottom slot put the cells that
make up the tooltip. The tooltips work together particularly well with the querylist in
the sense that a querylist can be used to create the contents of the tooltip.
</p>
<br/>
<br/><hr/>
<h3>Querylist (com.mbeddr.mpsutil.editor.querylist)</h3>
<p>
Normally, MPS can only project nodes at the location
where they resided physically on the model. So, while the rendering
of nodes could be designed arbitrarily, the structure of the projection
itself always had to conform to the structure of the underlying AST.
In other words, real views were not supported.
</p>
<p>
Enter querylist. A querylist is a list whose contents are the result
of an arbitrary query over the model. The elements in the list can
be editable, there are callbacks for what should happen when things
are added or deleted, and it is even possible to define wrapper
editors for the result elements or override the result element's
editor completely. Note that any MPS root editor can
project every node only once in an editable way. So if you are sure (by design) that
a particular querylist only shows nodes from other roots, you can leave it editable.
If it may show nodes from the same root, make sure you select the Duplicate Safe option.
Check out existing uses of the querylist for details on how to do this.
</p>
<p>
We are using this currently in two places. First, we use it to show
the signature of inherited operation-like constructs. In this case,
the queried elements are rendered in grey, and they are readonly.
The following picture shows this.
</p>
<br/>
<img src="/images/blog/querylist1.png"/>
<br/>
<br/>
<p>
The second location where we currently make use of this feature is
in assessments. So instead of just showing pointers to the result
elements in the assessment result, we can now show the actual element
inline. If the assessment is used to detect errors, then that error
can be fixed directly in the assessment instead of navigating to
the respective program location.
</p>
<br/>
<br/><hr/>
<h3>Hyperlink (com.mbeddr.mpsutil.hyperlink)</h3>
<p>
Hyperlink cells can be used for references in MPS. In contrast to normal reference cells
they automatically become blue and underlined if the mouse hovers over them (no Ctrl is
necessary). To make a reference a hyperlink, use the hyperlink-reference style attribute contributed
by the hyperlink language.
</p>
<br/>
<br/><hr/>
<h3>Breadcrumbs (com.mbeddr.mpsutil.breadcrumb)</h3>
<p>
Breadcrumbs are a way to improve the user's awareness where in a (big) file he is currently editing. It is essentially
a "horizontal tree" shown at the top of an editor that reflects the hierarchical structure of an editor's contents.
Niko has made an MPS extension that displays a breadcrumb in an MPS editor. By clicking on a label the user can jump
to the corresponding level of the containment hierarchy. By clicking on the little triangles one can see the remaining
nodes in the hierarchy.
</p>
<br/>
<img src="/images/blog/breadcrumbs.png"/><br/>
<br/>
<P>
To use breadcrumbs in an editor, only two simple steps are required. Nodes that form the hierarchy (and should show up
in the breadcrumb) must implement the interface <i>IBreadcrumb</i>. The root of the editor that should show the
breadcrumbs must include a <i>breadcrumb</i> editor cell at the top.
</P>
<br/>
<br/><hr/>
<h3>Outline (com.mbeddr.core.base)</h3>
<p>
MPS comes with an Outline view that opens when pressing Ctrl-F12. The view contains a
customizable list of contents in a root. It can be filtered by typing, and by pressing Enter,
the selected element can be selected in the editor. To have your own concepts show up
in this view, make them implement IShowUpInOutline.
</p>
<br/>
<br/><hr/>
<h3>Conditional Editor (de.slisson.mps.conditionalEditor)</h3>
<p>
In MPS, each language concept has its own editor. While this is useful in 99%
of all cases, sometimes it is a problem: imagine you want to change the editor
of many different language concepts at a time. Then you have to change the
editor for all these language concepts. This is tedious and error prone.
</p>
<p>
As an example, consider projecting a little arrow over all "things with names"
in C that are pointers as a means of highlighting pointers throughout the
program. This is shown in the example below.
</p>
<br/>
<img src="/images/blog/pointerArrowExample.png"/>
<br/>
<br/>
<p>
The problem here is that there are separate language concepts for local variable
references, global variable references, argument references, etc. All these
have to be changed.
</p>
<p>
Enter conditional editors. A conditional editor is almost like an aspect. It
can be applied "around" existing editor, and whether it applies or not is
determined by a condition and the applicable concept (similar to a pointcut in
AO). The figure below shows the definition of the pointer arrow editor.
</p>
<br/>
<img src="/images/blog/pointerArrowEditor.png"/>
<br/>
<br/>
<p>
It applies to all language concepts that are references and hence implement
the <i>IReference</i> interface. It is conditionally applied only if the type of the
reference is a pointer. As the editor itself, it shows the arrow (hiding
behind the <i>custom cell</i> on top of the already existing editor (<i>[next-editor]</i>).
</p>
<p>
Using this approach, it is now possible to essentially decorate any editor with
any decoration based on arbitrary conditions.
</p>
<br/>
<br/><hr/>
<h3>Richtext (de.slisson.mps.richtext)</h3>
<p>
With this extension you can use a non-structured, multi-line text editing cell in MPS editor.
It also allows you to insert real, structured program nodes into the otherwise unstructured
text, enabling mixed content editing. The details are explained in
<a href="http://voelter.de/data/pub/mpm13.pdf">this paper</a>.
</p>
<br/>
<br/><hr/>
<h3>RichString (com.mbeddr.mpsutil.richstring)</h3>
<p>
This BaseLanguage extension simplifies usage of variables and <a href="https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html">Java String.format()</a>
inside BaseLanguage Strings. Just add the language <tt>com.mbeddr.mpsutil.richstring</tt> to your model.
</p>
<p>
The following example shows referencing a simple variable, embedding an expression inside a string,
and the equivalent of calling <code>String.format()</code>.
<br/><img src="/images/blog/richstring.png"/>
</p>
<br/>
<br/><hr/>
<h3>File/Path Picker (com.mbeddr.core.base)</h3>
<p>
This is a language concept that supports picking paths and files from the file system.
The files are picked relative to several different roots (see below). The picker provides
code completion, opening the OS file/dir dialog, verifies that a file is valid and has
methods to return the absolute path for loading the file.
<ul>
<li><b>FileSystemDirPicker:</b> picks an absolute directory</li>
<li><b>MacroFilePicker:</b> picks a file relative to an MPS path variable</li>
<li><b>MacroFolderPicker:</b> picks a dir relative to an MPS path variable</li>
<li><b>SolutionRelativeFilePicker:</b> picks a directory relative to the current solution's root</li>
<li><b>SolutionRelativeDirPicker:</b> picks a file relative to the current solution's root</li>
</ul>
</p>
<br/>
<br/><hr/>
<h3>PlantUML Visualizations (com.mbeddr.mpsutil.plantuml)</h3>
<p>
This provides an integration of <a href="http://plantuml.com/">PlantUML</a> with MPS.
<a href="https://www.youtube.com/watch?v=QjwXITp6fwg">Watch this video to get an overview.</a>.
</p>
<p>
To use it in your own languages, implement the IVisualizable interface in your language
concept. Each concept can have several visualizations, called categories. The getCategories()
method returns the list (just strings). The getVisualization() method then returns the
actual visualition. It gets the user-requested category as an argument, as well as an empty
VisGraph object. The getVisualization() method then has to fill the VisGraph with the
actual visualiztion. This is done simply by using the add() method to build a native,
textual PlantUML visualization. Check out the existing implementations of the interface
to learn the deails; in particular, there is a helper method on VisGraph that creates
a URL for users to click on in the graph: createUrl(node).
</p>
<br/>
<br/><hr/>
<h3>Graph Diagrams (com.mbeddr.mpsutil.jung)</h3>
<p>
As an additional means of displaying relationships between nodes (next
to PlantUML and the tree views) we have integrated the <a
href="http://jung.sourceforge.net/">JUNG framework</a> for graph
display. As a language developer, you can implement an interface
<i>IJGraphProvider</i> and implement a method that creates the graph:
</p>
<ul>
<li>Programmable with high-level API
<li>Specify initial layout
<li>Configurable node size, color, line style and color, fill color, shape and label
<li>Configurable edge width, style, color and label
<li>Configurable tooltip text for nodes and edges
<li>Extensibility to plug in your own layouters (such as the one from yWorks)
</ul>
<p>
Once you have created a graph, your users have many options to view the
graph in an MPS tool window:
</p>
<ul>
<li>Double-click selects node or edge in editor
<li>Zoom and Pan
<li>Tooltips
<li>Selectable Layouts
<li>Selection and highlighting of outgoing and incoming nodes and edges
<li>Filtering based on node and edge type
<li>Filtering along a continuous axis (for example, time)
<li>Incremental, node-based collapsing and expansion
</ul>
<br/>
<center>
<a href="/images/blog/jung2.png"><img src="/images/blog/jung2.png" width="450"></a>
</center>
<br/>
<p>
The JUNG integration is available as part of mbeddr, but also as part
of the mbeddr.platform, so you can use it for your own languages. Check out
the <i>Chunk</i> node for an example of how to use it.
</p>
<p>
<a href="http://youtu.be/-v1X0GhsLJ4">A demo video of the viewer can be found here.</a>
</p>
<p>
To use it in your own language, implement the IJGraphProvider interface. Return a
JNGraph from the getGraph() method. Check out the existing implementations, and in
particular the DepGraphHelper (called from Chunk.getGraph()) to learn the details.
In short, a graph is built in two steps: the first step actually adds the nodes
and edges. The second step uses closures to style the graph. Examples can be seen
from DepGraphHelper.
</p>
<br/>
<br/><hr/>
<h3>TreeView (com.mbeddr.core.base)</h3>
<p>
Tree views are a proven way of showing and navigating structure in IDEs. MPS
of course has several of them for various purposes. We have now added a nice
tree view that can be used for various tasks. The screenshot below shows a call
stack for functions.
</p>
<br/>
<img src="/images/blog/treeview.png"/>
<br/>
<br/>
<p>
Selecting a node in the tree automatically selects the corresponding node in the editor.
In addition, tree nodes can contribute user-defined actions that are shown in the
context menu.
</p>
<p>
As with visualizations, a node can contribute different categories of tree
views. All of this can be defined without dealing with any Swing code. The code
below shows the implementation of the callgraph based on the interfaces ITreeViewable
and ITreeViewRoot.
</p>
<img src="/images/blog/treeviewcode.png"/>
<br/>
<br/><hr/>
<h3>Assessments (com.mbeddr.core.base)</h3>
<p>
MPS, like any other language workbench, supports various forms of constraint checks that
lead to errors or warnings, annotated directly to the element that fails the constraint check.
However, there are some kinds of checks that are different in nature: they may be global
and require expensive algorithms to compute. They may be used to create some kind of
overview, or report, and using error annotations spread all over the code may not be
suitable. You may also want to mark failed constraints as ok and ignore them in the
future. To support these use cases, we have added Assessments to mbeddr.
</p>
<p>
Here is an example assessment. It highlights all requirements in a model that have no
effort specified. Not having an effort is a problem, and you may want to keep track of
the requirements where you have yet to perform your estimation. The assessment shown below
shows an example result (of course, the results are references and you can navigate to
the offending requirement):
</p>
<p>
<center>
<img src="/images/assessment.png" width="350"/>
</center>
</p>
<p>
Note the colors. Green results are those that are marked as ok, so they are judged by the
user to not be a real problem. Red results are those that have been added during the last
update of the assessment. Black ones have been there from previous updates. Using the
colors, you can keep track of the current state of the assessment, as well as of its changes.
Assessment results are part of the model, so they are persisted and shared. They are
intended to be actively maintained and managed (in contrast to regular error or warning
annotations in the code). You can also set the “must be ok” flat to true, in which case the
Assessment itself gets an error annotation if the results contain non-ok entries.
</p>
<p>
The requirements thing above is of course just an example and the assessment facility
is extensible. You have to create two concepts:
<ul>
<li>A subconcept of AssessmentQuery, which has a behavior method to run the query and create the list of results</li>
<li>A subconcept of AssessmentResult, which is used to represent each "line" in the assessment result.</li>
</ul>
Check out the exisiting subconcepts to learn the details.
<p>
<br/>
<br/><hr/>
<h3>Property Default Values (com.mbeddr.mpsutil.propertydefault)</h3>
<p>
MPS does not allow default values for properties; this extension adds them.
</p>
<p>
Add the language <tt>com.mbeddr.mpsutil.propertydefault</tt> to the constraints
aspect of our concept. Due to limitations in MPS, we first need to add a "standard" constraint
for a property. Then, after selecting the whole constraint and pressing Ctrl-Space, we can select
the default property value, and assign any expression to it.
<br/><img src="/images/blog/propertydefault.png"/>
</p>
<br/>
<br/><hr id="targetchooser"/>
<h3>Target Chooser (com.mbeddr.mpsutil.targetchooser)</h3>
<p>
Sometimes you want to be able to select a location in the model where you want to modify
something. For example, in mbeddr's requirements, you may have an intention or refactoring
that allows you to move one or more selected requirements to another location. To make this
possible, you need a way to choose a node. The targetchooser dialog supports this, as
you can see from the following screenshot.
</p>
<p>
<center>
<img src="/images/targetchooser.png" width="500"/>
</center>
</p>
<p>
The target chooser supports limiting the scope of what is shown in the tree
(one or more solutions or models), lets you filter the contents of the tree (e.g., only
requirements modules and requirements) and lets you return an error message in case
the user selects an invalid target. The dialog also supports deep search; you can
just start typing and the matched node is highlighted, even if the respective subtree
has not yet been opened when the search is started.
</p>
<p>
To understand how to use the target chooser, take a look at the <a href="http://localhost:8080/select/com.mbeddr.cc/r:a85ddf64-0248-4e9b-81ab-306845f3da69/1802085703486799709/">moveToOtherModule</a> intention
in the requirements language.
</p>
<br/>
<br/><hr id="selectionintentions"/>
<h3>Selection Intentions (com.mbeddr.mpsutil.selection.intentions)</h3>
<p>
By default, an intention always applies to one node. Only refactorings can apply
to several nodes. However, refactorings work differently in the UI and it is hard
to explain to users when to use an intention and when to use a refactoring.
</p>
<p>
To address this problem, the selection intention can be used; it is not defined
for a particular concept, but for a particular selection (represented by a Java
class in MPS). As of now, there is a selection class for ranges of cells in tables
and a class for ranges (lists) of nodes. The latter one ic called NodeRangeSelection.
By defining an selection intention for a NodeRangeSelection, you can create an
intentions for several nodes at a time.
</p>
<p>
To understand how to use the selection intention, take a look at
the <a href="http://localhost:8080/select/com.mbeddr.cc/r:a85ddf64-0248-4e9b-81ab-306845f3da69/1802085703486799709/">moveToOtherModule</a> intention
in the requirements language.
</p>
<br/>
<br/><hr id="modellisteners"/>
<h3>Model Listeners (com.mbeddr.mpsutil.modellisteners)</h3>
<p>
MPS allows you to react to changing the values of properties and references, but it
does not allow you to adding or removing a child. This is a conceptual asymmetry, and
also a problem in several concrete cases. Model Listeners fix this problem.
</p>
<p>
They provide a new root for the Constraints model called Model Listeners. They are
defined for a particular concept and can react to adding of a child, removing a child
and before removing a child (while it is stil attached to its parent).
</p>
<p>
To understand how to use the it, take a look at
the <a href="http://localhost:8080/select/EMIExample1/r:7997f0fd-03cf-4899-b0e1-fc6ea1a5f5f1/5186809684116699888/">model listeners for Requirement</a>
in the Constraints of the requirements language.
</p>
<br/>
<br/><hr id="extensionclass"/>
<h3>Extension Class (com.mbeddr.mpsutil.extensionclass)</h3>
<p>
MPS already provides a language (jetbrains.mps.baseLanguage.extensionMethods) for defining extension methods,
i. e. methods to be called on an Object without being part of the Object's class. We extended this mechanism
to provide all static methods of a class as extension methods. They can be invoked on the type of the method's
first parameter.
</p>
<p>
Use the language com.mbeddr.mpsutil.extensionclass and create a new ExtensionClass root node. Point to the Java
class containing your static methods. If we like, we can add method annotations to overwrite parameter names, so
they are more elaborate than "p0" or "p2".
</p>