Can't figure out MPS error: "Child in the role X.Y does not belong to the concept X" - interface

I'm new to MPS, so this may be a stupid question, but I can't find a solution anywhere.
I'm defining two DSLs, where the first one is going to depend on the second.
I've defined a portion of the first language and so far so good.
I have a bunch of Concepts going, some Editors, Constraints etc.
I've created a model with an example node where I view what I've made.
Now I'm working on the second language and I went about exactly the same way as with the first.
I created a Concept that can be root. It's called 'Module'.
Then I defined an Interface Concept, called 'IModuleContent' and gave it to 'Module' as a child, calling it 'content' and setting the cardinality to [0..n].
Then I defined another Concept called 'Interface' that inherits from 'IModuleContent'.
I gave the two Concepts Editors, which are basically just curly brackets for now.
In my example model I create a new node from my new language. It gives me my root, a 'Module'. Because it's a named concept I give it a name. Then, inside the module's curly brackets I declare a new 'Interface'.
Together, it looks like this:
Module printeri {
Interface printer {
}
}
This all pretty much works, except that after giving 'Module' an instance of 'Interface' (so 'printer') as a variable, it gets underlined in red and the error reads:
"Child in the role Module.content does not belong to the concept Module"
However, I'm pretty sure that it does. All the concepts are in the structure of the new language and I believe everything is inherited the right way. I did practically the same thing in my first language and that works fine.
What's going on here?
EDIT: should have specified that I'm on version 2020.3

you can goto "File -> Invalidate Caches and Restart" if you think MPS behaves strange.
For me it looks like you did some changes, e.g. creating the "Module" node in youre examples and then change the structure like removing "content"-child and re-adding it. The problem here is that MPS does not resolves id-based and not name-based. By removing and re-adding a member definition you change the id. MPS is able to handle such changes in to a certain degree, e.g. by just pressing "F5" to refresh the editor. You can also click on the node and open the intentions menu via "ALT+ENTER" investigate the options suggested there.
Hope this background knowledge helps you a little bit with future problems :)
Best regards
Heiko
there seems to be a bug in the comment feature here, hi removes the "Hi Noah"

Okay, so it seems that the error has magically disappeared overnight.
Yesterday I closed MPS for the day and opened it again this morning.
Code completion wasn't working. Very annoying. So I restarted MPS.
On the second try code completion was working and the error from before was gone.
It seems like MPS may be a little unstable.
So yeah, for anyone running into the same issue:
Try the good old 'turn it off and on again' method.

Related

Possibility of a multilanguage 'source' name with Twincat Eventlogger

Roald has written an excellent guide for the Twincat Eventlogger.
https://roald87.github.io/twincat/2020/11/03/twincat-eventlogger-plc-part.html
https://roald87.github.io/twincat/2021/01/20/twincat-eventlogger-hmi-part.html
For us this is exactly what we want, there is however 1 thing I haven't figured out. How to get the sourcename of the alarm in multiple languages in the HMI. params::sourceName gives the path in the software (example: MAIN.fbConveyor1.Cylinder1) This path can be customized when initializing the alarm (as Roald has shown). This doesn't work in my case, since I would like to define a generic alarm (example: "Cilinder not retracted within maximum time") that is instantiated multiple times.
I was thinking of using the source as a way to show the operator where the alarm occurs. We use this way (path) already for saving machine settings among other things. The machines we build are installed all over the world, so multilanguage is a must.
Beckhoff does support multilanguage alarm names (when defined), but the source is not defined, but dynamically generated.
Anyone have an idea how this problem can be solved?
If I understand your question correctly, then being able to parameterize the event text with information of the source of the problem should help you out.
If you define the event text as Cylinder {0} has not retracted in time. then you can add the arguments of that text during runtime.
IF bRaiseAlarm THEN
bRaiseAlarm := FALSE;
fbAlarm.ipArguments.Clear().AddString('Alice');
fbAlarm.Raise(0);
END_IF
However, since this also stated in the articles you mentioned, I am unsure if this would solve your problem.
'Alice' in this example, can be hard to localize. The following options come to my mind.
The string can be based on an ENUM. Enums can have textlist support, so if you add your translations there, that should allow multilingual output. However... this does require a lot of setup, placing translations inside your code, and making sure the PLC application is aware of the language that the parameter should use.
Use tags to mark the source device, as tags can be language invariant. It is not the most user-friendly method, but it could work for you. It would become something like: "Cylinder 'AA.1123' did not retract in time.". 'AA.1123' as a tag would have to be stored inside your PLC code as a string. You will have to trust that your operator can relate the tag back to the actual source.
Hopefully, this helped, or else please help me understand the problem better.

what makes a variable be visible (intellij idea)

With intellij idea, how do I find out what makes a variable be visible?
An example of when it is hard:
Suppose you look at class A, and you see a variable something. If you jump to source you see that it's defined in trait X. But you don't extend trait X directly. What do you extend, then, that makes this variable visible? If you have a deeply nested hierarchy, tracking can be hard.
Any recommendations or solutions?
EDIT: Please vote for the feature if you're interested: http://youtrack.jetbrains.com/issue/IDEA-124369
I don't think that IntelliJ IDEA has any shortcut for "finding what makes a variable visible".
However you can determine it using the "Find Usages" option (Alt + F7). For example:
import java.nio._
object TempObj extends App {
def func = 2
val p = file.Paths.get("some-path")
func
}
So Find Usages on "file", tells you that its from the Package "file" (in heading of the new Tab it also shows the complete package name, ex: Find Usages of java.nio.file in Project Files).
Whereas Find Usages on func will tell you that its a Method (And the Tab heading now says: Find Usages of func() in Project and Libraries)
So now in way you can determine, what exactly makes the variable visible. This also works for imports since it shows the package from which it is imported and you can then look for import of that packages.
I know of two almost-solutions to this problem.
Go-to-declaration, as you mentioned, solves this problem in the case of local variables.
More generally, the "find usages" feature gives you a neat little breakdown by type and file of different uses of the variable. From this you can see if it's involved in a static import.
It's not perfect, but with a moment's thought these two are generally sufficient to figure out what you want.
Use ctrl+b or F4 to jump to source code. Alternatively you can use ctrl+shift+a to get option/action. You can find shortcuts at http://gaerfield.github.io/ide-shortcuts/ as well. Hope it will help.
From what I understood you want to see the code that creates an Object you use, for instance Mystery someMystery;.
That gives you two options to populate someMystery:
someMystery = ... where ... is your code to populate
someMystery and if that is the case you should follow
that code (with ctrl+B as far as you need to) to the point where it
actually creates the Mystery object.
Use CDI to populate that object instance for you, in which case you should look into the CDI mechanism in order to see in what way the object instance is populated.
In either way IMO there is no way to know for sure if the someMystery instance is of some more concrete class than Mystery, because it is decided in runtime, not in compile time, so your next bet would be to run the program in debug and see what object goes into someMystery, although you are not guaranteed to get the same type of object every time.
PS. My answer is based entirely on my java understanding of the topic, can't say if it is valid for scala also.
This might not be exactly the answer you were hoping to get.
However, quoting yourself,
If you have a deeply nested hierarchy, tracking can be hard.
Have you considered using composition over inheritance? Perhaps this would remove the need for the feature you are looking for.
Deeply nested hierarchy doesn't sound good. I understand your pain about that.
When you override vals or defs there is a little circle next to the line number that shows where it is from even when it is from nested hierarchy. Hovering over vals with the command key down also shows you a little tooltip where it is from.
Does this help?
https://youtu.be/r3D9axSlBo8
if you want class, field or method to be visible, you need to implement them as public. If it was your question.

How to disable Eclipse's "auto-folding during typing"?

Eclipse (any version AFAIK) has some weird behavior related to folding in Java code. Suppose I’m editing this class:
class A {
String field;
#Nonnull
Object method(){
// whatever
}
}
If folding is enabled and I tell it to collapse everything (it’s Control-NumSlash in mine, but that might be customized), the method is correctly folded, i.e. it shows only Object method()... for the method. All good ’till now.
The part that bothers me is that if I move the cursor right after field;, press Enter, and type something like “public”, and then stop for a second, Eclipse automatically folds that word into the method below.
That might seem reasonable (presumably it assumes I wanted to add that qualifier to the method); but in practice what I’m actually doing is trying to add a new method, and paused for a moment to think about its return type or maybe its name. (If I wanted to modify the method I’d unfold it first, since it might already have that qualifier, folded.)
I hate this “feature” with passion, but I can’t for the life of me find out how to disable it, nor even which of the damned mess of plugins (that Eclipse keeps insisting I should not be allowed to remove) is responsible for it so I can file a bug report.
So, does anyone know (1) where does that behavior come from, and hopefully (2) how can I get rid of it but keep manual folding? Thanks!
(For the record, I’m using Kepler SR1, but this behavior goes back a really long time, at least five years or so.)
I don't believe there's any way to prevent it from doing that unless you just make a habit of putting a semicolon ; or closing curly brace } after public which prevents the Object method(){.. from 'folding' it up. I believe it's written to fold everything up until the closest semicolon which is why #Nonnull is also included.
The only options for folding I can find are located in Window > Preferences > Java > Editor > folding
I would consider this to be a bug, or just a feature that had unintended side effects.
Funny enough, if you put almost any symbol or misspell public it wont fold it.

What is scala.mobile supposed to accomplish?

...and why has the package this misleading name (I assumed it had something to do with JavaME or mobile/smart phones)?
I found no references on the internet about scala.mobile.Code or scala.mobile.Location at all nor did I manage to do anything with those classes except getting ClassCastExcetions or NoSuchMethodErrors.
Actually there is not even a single test against scala.mobile in the Scala's test tree which could help understanding that code.
The classes really smell like they were forgotten in the source tree a long time ago and got accidentally released since that.
Maybe I just missed something about them?
Update:
scala.mobile was removed in Scala 2.9.
I just checked the source code.
When Scala changed the name mangling of class files a few years ago and it seems people forgot to update these classes accordingly.
So my answer would be:
At least Location has no purpose, because it is not possible to get anything sensible out of it (except exceptions) and Code without Location is severely limited. It works though if you pass the class literal to Code directly:
import scala.mobile._
val c = new Code(classOf[scala.collection.mutable.StringBuilder])
c.apply[StringBuilder, String]("append")("Foo")
c.apply[String]("toString")() // returns "Foo"
c.apply[Int]("length")() // returns 3
Looks like yet-another implementation in the standard library of reflection-slightly-nicer.
The description of Location pretty much explains what that is about:
The class Location provides a create method to instantiate objects
from a network location by specifying the URL address of the jar/class file.
It might be used by remote actors. Maybe.
As for why it has this misleading name? Well, back in 2004 smart phones had really low penetration, so maybe the association wasn't all that strong.

Are comments to show what version code was added/modified for useful?

Some of the developers on the project I work on have a habit of commenting their code to show which version of the product it was added for, e.g.
// added for superEnterpriseyWonder v2.5
string superMappingTag = MakeTag(extras);
if (superMappingTag.empty())
{
autoMapping = false;
}
// end added for superEnterpriseyWonder v2.5
Whenever I see this my blood pressure rises, and I have to spend 5 minutes browsing SO to cool off. It seems to me that they don't understand version control and if I were to use this practice too every other line in the source files would be a comment about when things were added. I'm considering removing all such comments from files that I work on, but am wondering is it just me being picky and is there actually some value to these comments?
If you're using Source Control then I would advocate adding a build label to Source Control after every build. That way you can search for all source modified for a specific build, with no nasty comments clogging your code.
This from Clean Code, a book by Bob Martin:
"The proper use of comments is to
compensate for our failure to express
ourself in code. Note that I used the
word failure. I meant it. Comments are
always failures."
I always think of that quote when I see a comment so I'm not suprised your blood boils.
No value whatsoever. If you have a blame tool in your version control this will achieve this, they just add noise.
Whats worse is they will attract further comments to your code to make it completely unreadable
// added for superEnterpriseyWonder v2.5
string superMappingTag = MakeTag(extras);
if (superMappingTag.empty())
{
// bug fix #12345674 shuld have been true
autoMapping = true;
// bug fix #12345674 should have been true
i++; // v2.6 now need to up the counter DO NOT DELETE
}
// end added for superEnterpriseyWonder v2.5
and then someone will delete the method but leave the code comment in
// added for superEnterpriseyWonder v2.5
// bug fix #12345674 should have been true
// v2.6 now need to up the counter DO NOT DELETE
// end added for superEnterpriseyWonder v2.5
Just say no to crappy comments
I'd say there's no value: This info can also be retrieved with your SCM's annotate/blame functionality. Also, anyone can add text between these comments, which make the comments dated (since you might add something for v2.6 while the comments say v2.5)
Another thing to note is that these comments are essentially hidden: You only see them when you are looking at the source code in question, so you can't use it to generate a changelog or something.
The comment as shown, is probably not to useful. However, there may be times that adding a feature may cause the addition of not so obvious code. In which case, a comment describing the change and/or why it the code is not obvious would be appropriate.
Not only is there no value here...there's negative value. Maintenance of comments is already sketchy in most places, this just adds another thing for people to screw with. These comments have no value to the reader and are therefore clogging their brain up with useless version information when they could have another line of code in their memory. It's also another line to have a merge conflict on (totally not joking here..I've seen merge conflicts on comments).
Could be useful in some cases (e.g. if this helps to understand why some function works differently in V3 than in V2) but in general, it's the job of the SCM to know what has been added when.
You are not picky IMHO. There are at least three good reasons not to add this type of comment in source code:
their place is actually in a Version Control System, where you can have a global view of everything that has changed to accommodate a new version of a library or a new feature. Provided it is done correctly and the logs are used.
if the source code is part of the deliverables to clients, maybe they don't need to know the history of what happened. Imagine you have done a modification for another client, and put that in comments!
too many comments are no better than too few.
The line is not clear though, what would be the difference between
// Compliance with specs abc (additional xyz feature)
...
... // some code
and:
// xyz feature:
...
... // some code
In general terms, I would not put anything that is related to the history in the source code, but stick to commenting what is done, how it is done, so that someone else can easily browse through the code and understand it.
My advice: have a methodology document written, or an informal discussion.
If seeing a superfluos comment makes your blood pressure rise, you need to take up drinking or something.
That said, I agree that such comments are mostly useless. If used consistently, the program would quickly become a maze of such comments. What if a line is changed once for version 2.5 and then a year later changed again for bug 3294? Do you put two "version" comments on the same line, or just keep the latest? If you only keep the latest, then you've lost the fact that this was originally added for 2.5. If you keep them both, what happens when there's a third change or a fourth? How do we know what the state was at each change? What happens when you add a block of code in version 2.5, and then for version 2.6 you add another block of code embedded within the 2.5 block? Etc etc. The program could easily end up having more version comments than lines of code.
If not done consistently, the comments would quickly become misleading. Someone could put a comment saying this block was added for 2.5, someone else could insert code inside that block for version 2.6 and not comment it, and now we have a comment that seems to say that the second block was added for 2.5.
And do we care that much? It's pretty rare that I care when a change was made. Oh, okay a couple of weeks ago I cared because I wanted to know who to blame for a major screw up.
As others have pointed out, version control systems do this for you on the rare occasions when you need it. I guess if you didn't have any sort of VCS, a case could be made for doing this. But you can get some very nice VCSs for free. If you need one, get one. Otherwise you're like the people who say that you should practice doing arithmetic in your head because otherwise what would you do if your calculator quit working. The assumption apparently being that at any moment, all the calculators in the world might simultaneously break.
You might say that it can help to be able to say, "Ohhhh, this was added to order entry to support the new salesman timecard function" or some such. But then the important this is not "This code was changed by Bob for version 3.2.4", but rather, "This code produces this data which isn't used here but is needed by another module over there".
I am a firm believer in writing comments that introduce sections of code and describe the general idea behind complex or otherwise non-obvious code. But that's an entirely different thing.
Consider that some may have to grab snapshots from the VCS. In that case, they don't have history to fall back on .. and such comments become useful.
I saw that a lot in code written by people that didn't use version control until recently. I guess they just took the habit and now it's hard to stop.
Another reason I found was that sometime it is important to know what piece of code is associated with what version. Of course you can always check the version log, but you don't always have time for that, and it's annoying. In some cases saying "code for v3.2" speaks more to other developers than "code to do x, y and z"... it all depends on the conventions established by the team.
Another answer is that in some projects I worked with some code was commented like that, but it was before the project actually started using version control. In that case it also made sense to keep it that way.
I find them useful, it saves chasing through the VCS to find out why a change was made to the code, or to find the BugId for a defect, given I remember what the code change was.
Although in theory the VCS contains the information, in practice it can get buried, particularly by integrations.
In other works which is easier:
// DEF43562 - changed default value
foobar = true
Or
blame(or equiv)
chase through
history to find the correct change.
Follow integration to source, and
repeat 1&2.
Find bug id attached
to original change, if you are
lucky.
Basically the comment is a short-cut around the VCS, and flaky VCS/BugTracking integration.
I find that the comments are also useful as a marker for: "This decision has been reviewed by customers/users/review committee, and this is the selected answer, be careful about changing the behaviour".