Auto alignment of data in Xtext - xtext

I had one custom parser rule in which I had defined all my keywords such as _self, _for, _loop etc. Because of this, if I type _s and click Ctrl+ space bar, it shows _self.But what I required is even though I type self or SE, it should auto assign as _self.Is it possible? If so, could anyone please suggest a solution for this. Thanks in advance

There are multiple things to be payed attention to
There needs to be a proposal and only one proposal. Otherwise the user has to select the prosal to be applied and no auto insert takes places
Proposals are created based on the error recovery and so you might not get the proposal you are looking for at all
so lets assume you have a grammar like
Model:
greetings+=Greeting*;
Greeting:
'_self' name=ID '!';
and a model file like
SE
Then the error recovery will work fine an a proposal of "_self" will be added to the list of proposals
Proposals are Filtered based on the current prefix in the model. that would be the place you could start customizing.
e.g. this very naive impl
import org.eclipse.xtext.ui.editor.contentassist.FQNPrefixMatcher;
public class MyPrefixMatcher extends FQNPrefixMatcher {
#Override
public boolean isCandidateMatchingPrefix(String name, String prefix) {
return super.isCandidateMatchingPrefix(name, prefix) || super.isCandidateMatchingPrefix(name, "_" + prefix);
}
}
and dont forget to bind
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import org.eclipse.xtext.ui.editor.contentassist.PrefixMatcher
import org.xtext.example.mydsl4.ui.contentassist.MyPrefixMatcher
#FinalFieldsConstructor
class MyDslUiModule extends AbstractMyDslUiModule {
override Class<? extends PrefixMatcher> bindPrefixMatcher() {
return MyPrefixMatcher;
}
}
There is another feature that does not use proposals at all but the text that is actually typed and if it recognizes something then can replace it with something else. this feature is called "Auto Edit". The extension point in xtext for this is IAutoEditStrategy / AbstractEditStrategyProvider

Related

Get declarations from an external source in Xtext

I have the following grammar:
Model: declarations += Declaration* statements += Statement*;
Declaration: 'Declare' name=ID;
Statement: 'Execute' what=[Declaration];
With that I can write simple scripts like:
Declare step_forward
Declare turn_right
Declare turn_left
Execute step_forward
Execute turn_left
Execute step_forward
Now I want that the java program provides all declarations, so that the script only contains the Execute statements. I read about IGlobalScopeProvider which seems to be the right tool for the job, but I have no idea how to add my data to it, and how to make Xtext use it.
So, how can I provide declarations from external to my grammar?
Update
My goal was somewhat unclear, so I try to make it more concrete. I want to keep the declarations as simple java objects, for instance:
List<Move> declarations = Arrays.asList(
new Move("step_forward"),
new Move("turn_right"),
new Move("turn_left"));
and the script should be:
Execute step_forward
Execute turn_left
Execute step_forward
I'm not really sure what you are asking for. After thinking about it, I cand derive th following possible questions:
1.) You want to split your script into two files. File a will only contain your declarations and File b then will only contain Statements. But any 'what' attribute will hold a reference to the declarations of File a.
This works out of the box with your grammar.
2.) You have any Java source code which provides a class which defines, for example a 'Declare Interface', and you want the 'what' attribute to reference to this interface or to classes which implement this interface.
Updated answer You should use Xbase within your language. There you can define that your 'what' attribute references to any Java type using the Xtypes rule 'JvmTypeReference'. The modifications you have to within your grammar are not that difficult, I think it could look this:
// Grammar now inherits from the Xbase grammar
// instead of the common terminals grammar
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
declarator=Declarator?
statements+=Statement*;
Declarator:
'Declare' name=ID;
Statement:
'Execute' what=JvmTypeReference;
The, you can refer to any Java type (Java API, any linked API, user-defined types) by adressing them with their qualified name. It would look like this:
Referring to JVM types look like this in an Xtext language. (Screenshot)
You can also validate whether the referenced JVM type is valid, e.g. implements a desired interface which I would define with one single, optional declarator in the model.
Referenced JVM type is checked whether it is a valid type. (Screenshot)
With Xbase it is very easy to infer a Java interface for this model element. Use the generated stub '...mydsl.MyDslJvmModelInferrer':
class MyDslJvmModelInferrer extends AbstractModelInferrer {
#Inject extension JvmTypesBuilder
#Inject extension TypeReferences
def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(
element.declaration.toInterface('declarator.' + element.declaration.name) [
members += it.toMethod("execute", TypesFactory.eINSTANCE.createJvmVoid.createTypeRef)[]
])
}
}
It derives a single interface, named individually with only one method 'execute()'.
Then, implement static checks like this, you should use the generated stub '...mydsl.validation.MyDslValidator' In my example it is very quick and dirty, but you should get the idea of it:
class MyDslValidator extends AbstractMyDslValidator {
#Check
def checkReferredType(Statement s) {
val declarator = (s.eContainer as Model).declaration.name
for (st : (s.what.type as JvmDeclaredType).superTypes) {
if (st.qualifiedName.equals('declarator.' + declarator)) {
return
}
}
(s.what.simpleName + " doesn't implement the declarator interface " + declarator).
warning(MyDslPackage.eINSTANCE.statement_What)
}
}
(I used the preferred Xtend programming language to implement the static checking!) The static check determines if the given JvmTypeReference (which is a Java class from your project) implements the declared interface. Otherwise it will introduce a warning to your dsl document.
Hopefully this will answer your question.
Next update: Your idea will not work that well! You could simply write a template with Xtend for that without using Xbase, but I cannot imagine how to use it in a good way. The problem is, I assume, you don't to generate the hole class 'Move' and the hole execution process. I have played around a little bit trying to generate usable code and seems to be hacky! Neverthess, here is my solution:
Xtext generated the stub '...mydsl.generator.MyDslGenerator' for you with the method 'void doGenerate'. You have to fill this method. My idea is the following: First, you generate an abstract and generic Executor class with two generic parameters T and U. My executor class then has an abstract method 'executeMoves()' with the return value T. If this should be void use the non-primitive 'Void' class. It holds your List, but of the generic type u which is defined as a subclass of a Move class.
The Move class will be generated, too, but only with a field to store the String. It then has to be derived. My 'MyDslGenerator' looks like that:
class MyDslGenerator implements IGenerator {
static var cnt = 0
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
cnt = 0
resource.allContents.filter(typeof(Model)).forEach [ m |
fsa.generateFile('mydsl/execution/Move.java', generateMove)
fsa.generateFile('mydsl/execution/Executor' + cnt++ + '.java', m.generateExecutor)
]
}
def generateMove() '''
package mydsl.execution;
public class Move {
protected String s;
public Move(String s) {
this.s = s;
}
}
'''
def generateExecutor(Model m) '''
package mydsl.execution;
import java.util.List;
import java.util.Arrays;
/**
* The class Executor is abstract because the execution has to implemented somewhere else.
* The class Executor is generic because one does not know if the execution has a return
* value. If it has no return value, use the not primitive type 'Void':
* public class MyExecutor extends Executor_i<Void> {...}
*/
public abstract class Executor«cnt - 1»<T, U extends Move> {
#SuppressWarnings("unchecked")
private List<U> declarations = Arrays.<U>asList(
«FOR Statement s : m.statements»
(U) new Move("«s.what.name»")«IF !m.statements.get(m.statements.size - 1).equals(s)»,«ENDIF»
«ENDFOR»
);
/**
* This method return list of moves.
*/
public List<U> getMoves() {
return declarations;
}
/**
* The executor class has to be extended and the extending class has to implement this
* method.
*/
public abstract T executeMoves();
}'''
}

How to set autocomplete="off" in vaadin

Is it possible to set HTML5 attribute autocomplete="off" on TextField in Vaadin 7?
I've searched but found no way to set attributes on text fields or just hint browser to disable native autocompletion on input fields in some other way in vaadin.
I think the only way if you use javascript:
TextField tf = new TextField();
tf.addStyleName("xyz");
JavaScript.getCurrent().execute(
"document.getElementsByClassName('xyz')[0].setAttribute('autocomplete', 'off')");
Extend the TextField...
package com.example;
import com.vaadin.ui.TextField;
public class MyTextField extends TextField {
// do other customization here as needed
}
...and - what's the key point here - its client-side Connector
package com.example.client;
import com.vaadin.client.ui.VTextField;
import com.vaadin.client.ui.textfield.TextFieldConnector;
import com.vaadin.shared.ui.Connect;
#Connect(com.example.MyTextField.class)
public class MyTextFieldConnector extends TextFieldConnector {
#Override
public VTextField getWidget() {
VTextField vTextField = super.getWidget();
vTextField.getElement().setAttribute("autocomplete","off");
return vTextField;
}
}
Don't forget to recompile the widget set.
If you use the Viritin add-on, you can now use the HtmlElementPropertySetter class to wrap your TextField component and use that to set the "autocomplete" element property to "off". You could also use the MTextField component that comes with Viritin and just create it as follows:
MTextField username = new MTextField("Username")
.withAutocompleteOff();
This is an extension to #Wojciech Marciniak's answer. His approach worked for me, but I want to note a couple or three modifications I had to do in order for it to work as of 2017/11/28.
1) autocomplete="off" don't seem to work anymore nowadays; at least not on Chrome. Instead, you can use autocomplete="new-password", which works on Chrome 62.0.3202.94 windows 64 bits. I also noticed some inconsistent behaviour with this attribute, as NOT always works - sometimes a list with choices for passwords will show up on the component (specially until you refresh a couple of times, etc.).
2a) Instead of extending the component, you may want to overwrite it by creating the com.vaadin.client.ui.(component)field package in your project, then put the modified (component)FieldConnector.java file in it (in my case I was modifying PasswordField) in case you want all your instances of this component to not remember passwords. The final class source should look like this:
package com.vaadin.client.ui.passwordfield;
import com.vaadin.client.ui.VPasswordField;
import com.vaadin.client.ui.textfield.TextFieldConnector;
import com.vaadin.shared.ui.Connect;
import com.vaadin.ui.PasswordField;
#Connect(PasswordField.class)
public class PasswordFieldConnector extends TextFieldConnector {
#Override
public VPasswordField getWidget() {
VPasswordField vTextField = (VPasswordField) super.getWidget();
vTextField.getElement().setAttribute("autocomplete","new-password");
return vTextField;
}
}
So this way you don't need any other class extending TextField (or PasswordField).
2b) If you want to allow some fields to remember passwords and other that don't, you can extend the component and use your preferred component accordingly. You can keep your connector class as in 2a) but remember to name it something like CustomPasswordFieldConnector, and it should also #Connect with that CustomPasswordField.class, put that class wherever it fits in your project and remember to add the proper import for it in the connector in case it's needed. This class is just a dummy one - you can leave its contents empty in case you don't need any extra functionality (but remember it should extend the proper (component)Field; PasswordField in the example).

Actionscript - shortcut reference to long class names

Is there a way to do something akin to import <BLAH> as in actionscript? I've got some classes that I don't want to type the full class name out for every time I use them. That's why I'm trying to find an import as, or var C = ImportedClassThatIDontWantToTypeEveryTime. I've tried a few different ways, such as:
package com.mysite.blah {
// doesn't work
import com.mysite.ImportedClassThatIDontWantToTypeEveryTime as C;
// also doesn't work
import com.mysite.ImportedClassThatIDontWantToTypeEveryTime;
var C:Class = ImportedClassThatIDontWantToTypeEveryTime;
// ????
public class SomeOtherClass {
public function blah():void {
C.doSomething();
}
}
}
I know there is a way to do this - I've done it before years ago. However, I can't remember how to do it. Help?
What IDE are you using? I ask this because I haven't had to type out a class-path in full in years. The auto-complete features of both FlashDevelop and FlashBuilder will allow you to type the first couple of letters of the class you want in place, select it from a list, and it will automatically add the appropriate import statement to the top of your class.

How to configure Xtext mwe.Reader to fill the root element in a slot

I am using Xtext 2.0 with MWE 1 and XPand, but I guess the Problem for MWE 2 and XTend is exactly the same.
My Xtext grammer looks like this (excerpt):
grammer org.test.Test with org.eclipse.xtext.common.Terminals
generate test "http://www.test.org/test/Test
Model :
"COMMON STUFF"
"{"
(formatterDefs+=FormatterDef)*
"}"
...
FormatterDef : "Formatter" name=ID ":" formatter=STRING;
When I use this mwe definiton (excerpt):
<component class="org.eclipse.xtext.mwe.Reader" path="${project.src.directory}/xtext/model/" >
<register class="org.test.TestStandaloneSetup"/>
<load slot='formatterDefs' type='FormatterDef'/>
</component>
<component class="org.eclipse.xpand2.Generator">
<metaModel class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
<expand value="templates::Formatter::formatterTxt FOREACH formatterDefs"/>
</component>
So the slot formatterDefs is filled with all FormaterDef, and then this is used for the template, and every think works fine.
But I have some templates that requires the model root element, named Model in the grammar. So I tryed to use
<load slot='formatterDefs' type='FormatterDef'/>
and
<expand value="templates::Main::main FOREACH model"/>
instead.
But then I get this warning:
org.eclipse.xtext.mwe.SlotEntry - Could not find any exported element of type 'Model' -> Slot 'model' is empty.
And the slot contains an empty list.
So my Question is: what do I need to do, to get the root Model into my templates?
I meant something like
public class MyDslNameProvider extends DefaultDeclarativeQualifiedNameProvider {
QualifiedName qualifiedName(Model m) {
return QualifiedName.create(m.eResource().getURI().toString());
}
}
public class MyDslRuntimeModule extends
org.xtext.example.mydsl.AbstractMyDslRuntimeModule {
#Override
public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() {
return MyDslNameProvider.class;
}
}
you could customize the IQualifiedNameProvider to give the Model a name.
~Christian
Probably the best way is inserting the text {Model} just at the beginning of the rule, to ensure the creation.
A solution was to add an ID to the Grammer Definiton of the Model.
Model : name = ID
"COMMON STUFF"
"{"
(formatterDefs+=FormatterDef)*
"}"
I understand that there was no existing Model element before, so after adding the ID the Model element must be created to contain the Id.
How ever may there is a better solution - I will accept it, as soon as it is posted.

DynamicJasper(on Grails) Purposefully keep column or field blank(empty)

I want to generate a pdf report, where a column(or cell/field) is left blank(empty) on purpose. This column actually does have a value but, I'm choosing not to display it. The column title still needs to be displayed.
Example of where this could be useful:
Blank(empty) column: A comments or notes column down one side of a report.
Blank(empty) cell: A sudoku puzzle print-out.
Much appreciated. DynamicJasper is Awesome! Thanks to the dj-team.
Regards,
Pete
Glad to announce, solution found for adding an 'empty' column - and in short, it's to create a customExpression.
def cb = ColumnBuilder.getInstance()
cb = cb.setTitle("Notes")
cb = cb.setCustomExpression(new BlankExpression())
AbstractColumn columnNotes = cb.build()
Then add it to the rest of the report.
Class BlankExpression is
public class BlankExpression implements CustomExpression {
public BlankExpression() { }
public Object evaluate(Map fields, Map variables, Map parameters) {
return " ";
}
public String getClassName() {
return String.class.getName();
}
}
But there are a few issues relating to the use of customExpressions and grails.
1st issue: "getNew()" - The examples provided on the DJ website all use "getNew()"
http://dynamicjasper.sourceforge.net/docs/HOWTO%20Create%20Custom%20Expressions.html is an example of DynamicJasper v3.1.3 where as the Grails plugin is based on v.3.0.6 which only has a getInstance() method (deprecated in 3.1.3)
2nd issue: As far as I can see, groovy doesn't allow java-style inline class implementations, thus forcing us to create a separate class file. But this is not a big problem. I might be wrong about this, and please correct me.
Hope this helps you too.
Regards,
Pete

Resources