I'm trying to make a reshaprer plugin to add one (or more) configurations, besides executable, static method, project, at resharper's build/run window.
Any guidelines where to start? Or how to access build's context and configure?
Currently examining the JetBrains.IDE.RunConfig, SolutionBuilders etc but one help would be appreciated.
Should this plugin be a SolutionComponent or a SolutionInstanceComponent?
Resharper's sdk help lucks documentation on build/run component.
Thank in advance!
You can extend the available run configuration types by implementing IRunConfig and IRunConfigProvider.
The IRunConfigProvider class needs to be marked as [ShellComponent], and can derive from the RunConfigProviderBase abstract base class. You get to specify a name, e.g. "Executable", a type identifier, e.g. "exe" and an icon ID. There's also the CreateNew method, which will create a new instance of your IRunConfig class, which will be mostly unconfigured, at this point.
The IRunConfig interface doesn't need to marked as a component, and should also derive from RunConfigBase - take a look at RunConfigExe in dotPeek to see an example of how to implement. You should override Execute in order to actually run whatever it is you need to run. You can use the RunConfigContext class passed in to actually execute a process from a ProcessStartInfo, or an IProject - this will execute it either by running the process, debugging it, or something else, such as code coverage or profiling.
For an .exe, this is as simple as:
public override void Execute(RunConfigContext context)
{
context.ExecutionProvider.Execute(GetStartInfo(context), context, this);
}
But for a more complicated example, look at RunConfigMethod.Execute, which uses its own standalone launcher executable, and passes in command line parameters to load the correct assembly and execute the given static method.
Settings are implemented with ReadSpecific/SaveSpecific, and you can provide an editor view model with CreateEditor. You'll need a settings class, something like:
[SettingsKey(typeof (ConfigSettings), ".exe config")]
public class ExeSettings
{
[SettingsEntry(null, "Path to .exe")] public string Executable;
[SettingsEntry(null, "Working directory")] public string WorkingDirectory;
[SettingsEntry(null, "Command line arguments")] public string Arguments;
}
The view for the editor is provided by a WPF control that is displayed in a dialog that ReSharper controls. The view needs to be decorated with the [View] attribute and must implement IView<T> where T is the concrete class returned from CreateEditor. This is how ReSharper will locate the view for the view model returned by CreateEditor. Again, take a look at RunConfigMethodView in dotPeek for some more idea of what's going on (and if you look in the resources, you'll be able to see the XAML itself).
Related
This question relates to ReSharper. If I have an interface that looks like this:
public interface IOrder {
Task SetDeleted(Guid id);
}
and my class inherits from that interface, I would expect ReSharper to generate the following code, when selecting the "Implement missing members":
public class OrderService {
public async Task SetDeleted(Guid id) {
throw new NotImplementedException();
}
}
However, it completely ignores the async part of the method, so I have to type that manually every single time. This was fixed in 2016.3 of ReSharper, as described here (at the bottom).
However, it does not work for the CTRL + . keybinding (or whatever it is), that looks like this:
Is it possible to somehow change, how this behavior works within ReSharper? I want all generated Task methods to be async automatically. There is no option within ReSharper's "Members Generation" that enables me to do this.
In case class has only one missing member ReSharper doesn't show dialog therefore you can't tweak generation options. But you can add one more member to your interface and invoke generation action, this time ReSharper would show the dialog where you can set option "Make task-returning methods 'async'". This generation option is persistent i.e. it's last value will be stored in ReSharper settings and used by default.
I have a custom view called IconView, which has the following constructor for initialization:
public class IconView extends RelativeLayout implements Checkable {
...
public IconView(Context context, AttributeSet attrs, boolean useDefaultImage) {
super(context, attrs);
inflateLayout(context);
...
In order to initialize AttributeSet instance from XMLfor constructing the view, I use getResources().getXml(R.layout.icon_view), false);.
This compiles successfully and runs correctly. However, Android studio highlights the code and displays me this error:
The detailed description of the error is here:
Expected resource of type xml less... (Ctrl+F1)
Reports two types of problems:
Supplying the wrong type of resource identifier. For example, when
calling Resources.getString(int id), you should be passing
R.string.something, not R.drawable.something.
Passing the wrong
constant to a method which expects one of a specific set of
constants. For example, when calling View#setLayoutDirection, the
parameter must be android.view.View.LAYOUT_DIRECTION_LTR or
android.view.View.LAYOUT_DIRECTION_RTL.
The question:
Although the code works, I do not know, how to rewrite it, so that the error would disappear in Android Studio. The error is visually annoying, so how could I get rid of it?
Resources#getXml(int id) is used to get the resource of type xml, which lays inside the xml resource folder. You, on the other hand, passing R.layout.icon_view here, the layout resource.
Use getResources().getLayout(R.layout.icon_view) here and the error will disappear.
P.S.: the documentation on Resources#getLayout() says the following:
This function is really a simple wrapper for calling getXml(int) with a layout resource.
So it looks like this is some kind of lint-related issue. Either way, getLayout() does not result in this error.
I have created a Visual Studio extension that provider syntax highlighting by implementing IClassifierProvider. I would like to add additional features such as support for the standard Edit.CommentSelection and Edit.FormatDocument commands, but I have no idea how to do that. All the documentation I can find is about adding new commands, but the commands I want to handle already exist.
How can I handle these commands?
I considering the specific Comment Selection and Uncomment Selection commands you refer to as special cases, because I'm working on a Commenter Service specifically intended to support these two actions. The service is being developed on GitHub and will be released via NuGet when it is ready. I'll start with a description of this service, and follow with some general information about implementing support for specific commands, including the Format Document command.
I would like to release the library and its dependencies this week, but the restriction that the Commenter Interfaces assembly be an immutable assembly demands more testing than is generally given to a library prior to its initial release. Fortunately the only thing in this particular assembly is two interfaces is the Tvl.VisualStudio.Text.Commenter.Interfaces namespace.
Using the Commenter Service
Source: Commenter Service (Tunnel Vision Labs' Base Extensions Library for Visual Studio)
This services allows extension developers to easily support the Comment and Uncomment commands for new languages in Visual Studio.
Providing a Standard Commenter
The easiest way to provide commenting features is to use the standard Commenter implementation of the ICommenter interface. The following steps show how to create an instance of Commenter and provide it to the Commenter Service by exporting an instance of ICommenterProvider.
Create a new class derived from ICommenterProvider. This class is exported using the MEF ExportAttribute for one or more specific content types using the ContentTypeAttribute. The commenter in the example supports C++-style line and block comments, for the SimpleC content type.
[Export(typeof(ICommenterProvider))]
[ContentType("SimpleC")]
public sealed class SimpleCCommenterProvider : ICommenterProvider
{
public ICommenter GetCommenter(ITextView textView)
{
// TODO: provide a commenter
throw new NotImplementedException();
}
}
Define the comment format(s) the commenter will support.
private static readonly LineCommentFormat LineCommentFormat =
new LineCommentFormat("//");
private static readonly BlockCommentFormat BlockCommentFormat =
new BlockCommentFormat("/*", "*/");
Implement the GetCommenter(ITextView) method by returning an instance of Commenter. The ITextUndoHistoryRegistry service is imported in order for Commenter to correctly support the Undo and Redo commands. The following code is the complete implementation of ICommenterProvider required to support the Comment and Uncomment commands for a simple language.
[Export(typeof(ICommenterProvider))]
[ContentType("SimpleC")]
public sealed class SimpleCCommenterProvider : ICommenterProvider
{
private static readonly LineCommentFormat LineCommentFormat =
new LineCommentFormat("//");
private static readonly BlockCommentFormat BlockCommentFormat =
new BlockCommentFormat("/*", "*/");
[Import]
private ITextUndoHistoryRegistry TextUndoHistoryRegistry
{
get;
set;
}
public ICommenter GetCommenter(ITextView textView)
{
Func<Commenter> factory =
() => new Commenter(textView, TextUndoHistoryRegistry, LineCommentFormat, BlockCommentFormat);
return textView.Properties.GetOrCreateSingletonProperty<Commenter>(factory);
}
}
Command Handling in Visual Studio
The following are general steps for handling commands in Visual Studio. Keep in mind that the implementation details are quite complicated; I've created some abstract base classes to simplify specific implementations. After this overview, I will point to both those and a concrete example of their use for you to reference.
Create a class which implements IOleCommandTarget. The QueryStatus method should check for the specific commands handled by your command target and return the appropriate status flags. The Exec method should be implemented to execute the commands.
Register the command target with a specific text view by calling IVsTextView.AddCommandFilter. If you are working with an MEF-based extension, you can obtain the IVsTextView by either exporting an instance of IVsTextViewCreationListener, or by importing the IVsEditorAdaptersFactoryService component and using the GetViewAdapter method to obtain an IVsTextView from an instance of ITextView.
Here are some specific implementations of the interfaces described here:
CommandFilter: This class implements the basic requirements for IOleCommandTarget
TextViewCommandFilter: This class implements additional functionality to simplify the attachment of a command filter to a text view
CommenterFilter: This class is a concrete implementation of a command filter used by the Commenter Service implementation to handle the Comment Selection and Uncomment Selection commands
I have a custom type converter that converts UTC DateTime properties to a company's local time (talked about here: Globally apply value resolver with AutoMapper).
I'd now like to only have this converter do its thing if the property on the view model is tagged with a custom DisplayInLocalTime attribute.
Inside the type converter, if I implement the raw ITypeConvert<TSource, TDestination> interface, I can check if the destination view model property being converted has the attribute:
public class LocalizedDateTimeConverter : ITypeConverter<DateTime, DateTime>
{
public DateTime Convert(ResolutionContext context)
{
var shouldConvert = context.Parent.DestinationType
.GetProperty(context.MemberName)
.GetCustomAttributes(false)[0].GetType() == typeof(DisplayInLocalTimeAttribute);
if (shouldConvert) {
// rest of the conversion logic...
}
}
}
So this code works just fine (obviously there's more error checking and variables in there for readability).
My questions:
Is this the correct way to go about this? I haven't found anything Googling around or spelunking through the AutoMapper code base.
How would I unit test this? I can set the parent destination type on the ResolutionContext being passed in with a bit of funkiness, but can't set the member name as all implementors of IMemberAccessor are internal to AutoMapper. This, and the fact that it's super ugly to setup, makes me this isn't really supported or I'm going about it all wrong.
I'm using the latest TeamCity build of AutoMapper, BTW.
Don't unit test this, use an integration test. Just write a mapping test that actually calls AutoMapper, verifying that whatever use case this type converter is there to support works from the outside.
As a general rule, unit tests on extension points of someone else's API don't have as much value to me. Instead, I try to go through the front door and make sure that I've configured the extension point correctly as well.
How can we add some common constraints (i.e. maxLength, nullable) to a property of a Groovy class? I know we can do it at Grails domain class, but is it possible if that is a Groovy class (I use it as a DTO class for my Grails project)?
Thank you so much!
You can add constraints to command classes. If a command class is in the same .groovy file as a controller (in Groovy you can have more than one public class in each .groovy file), you don't need to do anything special for Grails to recongise it as a command class.
However, if your command class is somewhere else (e.g. under src/groovy), you need to annotate it with #Validateable and add the package name to the grails.validateable.packages parameter in Config.groovy. Here's an example of a command that's not in the same file as a controller
pacakge com.example.command
#Validateable
class Person {
Integer age
String name
static constraints = {
name(blank: false)
age(size 0..100)
}
}
Add the following to Config.groovy
grails.validateable.packages = ['com.example.command']
Command classes have a validate() method added by Grails. After this method is called, any errors will be available in the errors property (as per domain classes).
Using a grails Command Object is probably your best bet. It has constraints and validation, but no database backing. It's normally a value object that controllers use, but you could instantiate one outside of a controller without any problems.
Not sure if this is relevant to your use (I am not familiar with DTOs), but in the current version (2.3.8), you can also add Grails constraints to an abstract class, and they will be inherited by the domains that extend it. Your IDE might not like it though ;)