How to invoke a Eclipse Clean-Up Profile programmatically? - eclipse

Is there a way to invoke a specific Clean-Up profile (Source->Clean Up) programmatically?
I would like to invoke it on an iterable of ICompilationUnits.

I looked at the declarations in org.eclise.jdt.ui.
The relevant command ID is org.eclipse.jdt.ui.edit.text.java.clean.up and the implementation is org.eclipse.jdt.internal.ui.actions.AllCleanUpsAction. Unfortunately it is an internal action and the command does not support any parameters.
I can see three possible approaches:
create an AllCleanUpsAction and invoke ...run(new StructuredSelection(<compilation units>[])). Problem: the action is internal so you might want to create a fragment to access it...
open the package navigator view. Select the proper files corresponding to the compilation units. Execute the command ID via IHandlerService.executeCommand("org.eclipse.jdt.ui.edit.text.java.clean.up"). Problem: the package navigator is changed... and you might not have all compilation units in visible in the navigator.
set the current selection in your view to new StructuredSelection(<compilation units>[]). Then execute the command as above. Problem: I'm not sure the command is properly enabled..

You can use RefactoringExecutionStarter.startCleanupRefactoring which takes an array of ICompilationUnits to perform the clean up on as one of its parameters. This method also allows you to specify the ICleanUps that you want to perform and allows you to skip showing the clean up wizard if you want.
Here's an example which removes unnecessary parentheses:
ICleanUp[] cleanUps = new ICleanUp[]{new ExpressionsCleanUp(){
#Override
protected boolean isEnabled(String key){
switch(key){
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES:
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_NEVER:
return true;
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_ALWAYS:
return false;
default:
return super.isEnabled(key);
}
}
}};
ICompilationUnit[] icus = new ICompilationUnit[]{icu};
Shell shell = HandlerUtil.getActiveEditor(event).getSite().getShell();
try {
RefactoringExecutionStarter.startCleanupRefactoring(
icus, cleanUps, false, shell, false, ActionMessages.CleanUpAction_actionName);
} catch (InvocationTargetException e) {
throw new AssertionError(e);
}

Related

Get newly created id of a record before redirecting page

I would like to retrieve the id of a newly created record using javascript when I click on save button and just before redirecting page.
Do you have any idea please ?
Thank you !
One way to do this in Sugar 7 would be by overriding the CreateView.
Here an example of a CustomCreateView that outputs the new id in an alert-message after a new Account was successfully created, but before Sugar gets to react to the created record.
custom/modules/Accounts/clients/base/views/create/create.js:
({
extendsFrom: 'CreateView',
// This initialize function override does nothing except log to console,
// so that you can see that your custom view has been loaded.
// You can remove this function entirely. Sugar will default to CreateView's initialize then.
initialize: function(options) {
this._super('initialize', [options]);
console.log('Custom create view initialized.');
},
// saveModel is the function used to save the new record, let's override it.
// Parameters 'success' and 'error' are functions/callbacks.
// (based on clients/base/views/create/create.js)
saveModel: function(success, error) {
// Let's inject our own code into the success callback.
var custom_success = function() {
// Execute our custom code and forward all callback arguments, in case you want to use them.
this.customCodeOnCreate(arguments)
// Execute the original callback (which will show the message and redirect etc.)
success(arguments);
};
// Make sure that the "this" variable will be set to _this_ view when our custom function is called via callback.
custom_success = _.bind(custom_success , this);
// Let's call the original saveModel with our custom callback.
this._super('saveModel', [custom_success, error]);
},
// our custom code
customCodeOnCreate: function() {
console.log('customCodeOnCreate() called with these arguments:', arguments);
// Retrieve the id of the model.
var new_id = this.model.get('id');
// do something with id
if (!_.isEmpty(new_id)) {
alert('new id: ' + new_id);
}
}
})
I tested this with the Accounts module of Sugar 7.7.2.1, but it should be possible to implement this for all other sidecar modules within Sugar.
However, this will not work for modules in backward-compatibility mode (those with #bwc in their URL).
Note: If the module in question already has its own Base<ModuleName>CreateView, you probably should extend from <ModuleName>CreateView (no Base) instead of from the default CreateView.
Be aware that this code has a small chance of breaking during Sugar upgrades, e.g. if the default CreateView code receives changes in the saveModel function definition.
Also, if you want to do some further reading on extending views, there is an SugarCRM dev blog post about this topic: https://developer.sugarcrm.com/2014/05/28/extending-view-javascript-in-sugarcrm-7/
I resolved this by using logic hook (after save), for your information, I am using Sugar 6.5 no matter the version of suitecrm.
Thank you !

Unable to modify Coffeescript's global variables in a JQuery listener

Today I was migrating some of my javascript code into coffeescript and got stuck in something really silly but even though I didn't know how to make it work.
I wanted to update the value of a global variable when a click event was triggered, have a look at the code below to see one of my guesses
Here's the code
#activeObject = null
# Some other code
$ ->
$('#header').click ->
if !headerSelected
showMenu '#header-menu', event
else
#activeObject = "#header"
showMenu '#menu-style-header', event
Unfortunately even though the click event was triggered the variable was not getting updated.
I came up with a work around. I created a function that set the value of the variable and called it instead of the assignment and this time it worked.
I just wanted to know why I wasn't able to do it the other way. For me it was a simple operation and it seemed silly to define a new function just for this.
Your problem is that # (AKA this) inside the click handler isn't the same as it is outside so this:
#activeObject = null
and this:
#activeObject = "#header"
are referring to two different activeObjects. You should be able to bind everything with => to get the right this:
$ =>
$('#header').click =>
#...
or better (IMHO), just refer to window.activeObject directly in both places so that it is obvious to everyone that you're referring to a global variable:
window.activeObject = null
$ ->
$('#header').click ->
if !headerSelected
showMenu '#header-menu', event
else
window.activeObject = "#header"
showMenu '#menu-style-header', event
Alternatively, you could stop using globals altogether in favor of, perhaps, a data attribute:
$ ->
$('#header').data 'activeObject', null
$('#header').click ->
if !headerSelected
showMenu '#header-menu', event
else
$(#).data 'activeObject', '#header'
showMenu '#menu-style-header', event
I think the confusion is about the usage of #, which is basically just a shortcut for this.
If you compile your code and see what CoffeeScript compiler it produces, the confusion becomes clear
this.activeObject = null;
$(function() {
return $('#header').click(function() {
if (!headerSelected) {
return showMenu('#header-menu', event);
} else {
this.activeObject = "#header";
return showMenu('#menu-style-header', event);
}
});
});
if activeObject is global you whould reference to it
window.activeObject = null
and
window.activeObject = "#header";
in both occurences in this code, cause one might be tempted to use it without window in second occurence, but that will cause a new local variable to be implecitly defined.
Generally when starting with CoffeeScript, its usefull to try small snipets like this in
http://coffeescript.org/ on the Try Now Tab

Defining Window for Testing in Mocha

I'm trying to integrate some testing into my current Backbone/CoffeeScript application.
I have created a module for my application baked into the window object, but running any mocha tests fail because window is undefined.
module = (name) ->
window[name] = window[name] or {}
module 'Cart'
Any direction as to how I can define window for mocha?
I did try using jsdom and creating a window that way, but it still threw the same error. Thanks in advance.
EDIT:
Using zombie.js is getting me further then using jsdom.
zombie = require 'zombie'
browser = new zombie.Browser
browser.window.location = 'http://local.cart'
I'm trying to figure out a way to access the DOMWindow and set a variable to one of its values.
It would be ideal if browser.window was the same object as returned from accessing window in Chrome console, but it isn't.
I can access what I'm looking for with
zombie.visit 'http://local.cart', (err, browser) ->
throw err if err
browser.window.Cart
Is there a way for me to set what this returns to a global variable I can use throughout all of my specs?
Can't seem to get what I want trying a beforeEach or setting the previous block to a method and setting a variable to that method.
I think you'll definitely want to mock window, as opposed to trying to pass around a real DOM window object in the node side of your app (mocha).
Try this pattern I just whipped up (sort of conforms to mocha tutorials I have read and uses the this context which changes when in browser (window) vs. run on node (exports):
/**
* My namespace is 'AV'
*/
(function(root) {
/**
* #namespace root namespace object
*/
root['AV'] = root['AV'] || {};
var AV = root['AV'];
AV.CoolThing = {
//...
};
// this will give you
// your "window" object
// which is actually
// module.exports
return root;
})(this);
Then, the test might look something like this (mine are in coffeescript too):
chai = require 'chai'
chai.should()
# exports / "window"
{ AV } = require '../src/AV.js'
describe 'Sample test with namespace', ->
it 'should be an object', ->
AV.should.be.an 'object'

In Install4j, How to set a relative path in varfile?

I have an install4j project that I'm running from both GUI and command line.
As you might know it is possible to pass installer parameters in varfile.
I would like to know if there is a simple way to give a relative path in the varfile in the form:
my.variable=${installer:installerDir}\a.txt
I can see a workaround where I can ask the user to specify the file name only and I will put the directory path in the code. but I would still like to know if this is possible.
Thanks.
Ika.
You cannot use installer variables in the variable file. That file is read at startup before any other installer variables are defined, so you would not have a chance to set up the "installerDir" variable first.
The only option I see here is to use your own token, say
my.variable=#installerDir#\a.txt
and use a "Run script" action in the "Startup" node to replace that token with a particular directory. Here's some which checks all defined variables:
String installerDir = null;
InstallerContext context = null;
for (Object o : context.getVariableNames()) {
String variableName = (String)o;
Object variableValue = context.getVariable(variableName);
if (variableValue instanceof String) {
String replacedValue = ((String)variableValue).replaceAll("#installerDir#", installerDir);
if (!replacedValue.equals(variableValue)) {
context.setVariable(variableName, replacedValue);
}
}
}

return statement from within using

using (IDbCommand command = new SqlCommand())
{
IDbDataAdapter adapter = new SqlDataAdapter();
DataSet ds = new DataSet();
adapter.SelectCommand = command;
command.Connection = _dataAccess.Connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "GetProcData";
command.Parameters.Add(new SqlParameter("#ProcID ", procId));
adapter.Fill(ds);
return ds.Tables[0].AsEnumerable();
}
This returns an IEnumerable DataRow The question is that since the return is within the using statement, will it property dispose of the IDBCommand? I know I can easily refactor this so I change the scope of the DataSet outside of the using, but it is more of a wonder than anything else.
Yes, this will work as expected with IDbCommand being properly disposed. The compiler will transform the using block to a try-catch-finally, where Dispose is invoked in the finally block.
Yes, the DB Command will be disposed, so far so good.
You can get troubles with IEnumerables. Because the items could potentially be produced when getting them from the IEnumerable, not when creating the IEnumerable, that is the nature of it. So it depends on how ds.Tables[0].AsEnumerable() is implemented. It could wait with executing the command until you get the first item. This is in the calling code, outside of the using block. You'll get an error, because the command had been disposed.
This is probably not an issue here, but should always be considered when returning IEnumerables (or lambda expressions) from a using block:
using (A a = new A())
{
return someItems.Select(x => a.Get(x));
}
When accessing the first item, a is already disposed and you get an error.
The IDbCommand is disposed correctly. As a rule of thumb when returning from within a using statement you are fine to do so so long as:
The thing you are returning isn't in the clause of the using
statement
The thing being returned isn't a reference created within the block of the using statement.
In the first case the using statement will dispose of the thing you are trying to return and in the second case the variable will go out of scope.
e.g.
//this is fine as result is createsd outside the scope of the block.
bool result = false;
using (SmtpClient mailClient = new SmtpClient())
{
try
{
mailClient.Send(...);
result = true;
}
catch(SmtpException)
{
result = false;
}
finally
{
return result;
}
}
Here, the using(){ ... } statement is our friend. When we exit the block our SmtpClient is disposed, and the result condition will still exist for you to use.
However, say we are writing a WinForm app or WPF app and we wrap a using block around our data context then we create a problem as the context disappears before the control can consume it.
// this will fail when you bind the customers to a form control!
using (DbContext context = new DBContext())
{
context.Customers.Where(c => c.Name.Contains("Bob")).Load();
return context.Customers.Local;
}
Here, the using(){ ... } statement hurts us. As when we come to dataBind our customer to a GridView (or other such databound control) the fact that we have disposed of the DbContext will mean our form has nothing to bind to so it will throw an exception!
HTH
The scope of your IDbCommand object is very clear: between the brackets { and }. As soon as your program flow exits from there, the object is disposed.