Wednesday, December 12, 2007

CreateStubForHandler - How does it work?

Our good friend Koen Hoefkens suggests that there might be some interest around the inner workings of the newly refactored CreateStubForHandler.

Versions
There are 2 versions of the plugin. One for DXCore 2.x (for VS2003) and another for DXCore 3.x (for VS2005 and VS2008).

This was done for 2 reasons:
Koen (the original author) has a few projects kicking around in VS2003, and so we needed to maintain a version of the code capable of producing a version of the plugin that could likewise run under the DXCore 2.x and hence under VS2003. I have a virtual machine setup to run VS2003 under XP and so I am in a position to test this project at my end if need be.

DevExpress have recently released a beta of DXCore 3.0 along with companion copies of RefactorPro and CodeRush. Now these new betas (like the full versions which will follow) only run inside of VS2005 or better but provide some interesting features which are not available in previous versions. Therefore I thought it would be good to create a version of the code which would take advantage of these new features where possible.

So to meet both of these requirements, we have divided the project into 2 parts and therefore 2 directories. The main trunk of the project contains directories called 'VS2003' and 'VS2008'. These house the Solutions and further directories and Projects suited to those environments.

Triggering the plugin
Each Project contains a plugin class created from a template drawn from the appropriate DXCore. These Plugin classes each use techniques and technology again suited to the version of the DXCore that they support. The DXCore 2.x uses an Action and a RefactoringProvider to trigger the plugins main functions, while the VS2008 version uses the same action logic together with a CodeProvider to achieve a similar effect.

The inner workings are the same for each due to their sharing of a common "PluginLogic.vb" file which lives in the VS2003 folder structure and is linked to from the VS2008 solution.

How does it work?
Essentially what happens is that whether activated by Action, RefactoringProvider or CodeProvider, much the same thing happens.

We have a main function "CreateMethodStub" which is passed 3 parameters:

  1. CaretElement: A LanguageElement which represents the element of code next to the caret at the time of activation. We can use a LanguageElement here because we're talking about an object on the sourcecode.
  2. InsertionPoint: A SourcePoint which tells the plugin where the newly generated method should be placed.
  3. CompleteStatement: A boolean indicating whether or not the AddHandler/RemoveHandler statement requires completion.

This function is responsible for organising the various stages of the plugin's operation. You can think of it as the core of this plugin. It delegates to other functions to do almost everything and then triggers the expansion of the code into the Active Document.

Build the New Method
The first step in generating code using the DXCore is to choose the correct root LanguageElement. That would be "Method" in this case since we are trying to create a method.

Next it's all about adding other suitable LanguageElements to that Method in the correct places and waving the "DXCore Magic Code Generation Wand".

Creating a method is easy:
-------------------------------------------------------------
Dim Method As New Method(MethodName)
Method.MethodType = MethodTypeEnum.Void
-------------------------------------------------------------
..Next we need to add some parameters which is normally easy also:
-------------------------------------------------------------
Dim SomeParam as New Param("System.String",ParamNameHere)
-------------------------------------------------------------

Constructing the correct signature
The difficulty here is that we can't just create any old parameters. We have to create parameters suited to the Event for which we are creating our handler method.

So how do work out what those are then?

If you need a quick refresher on why we're using IElement derived interfaces then take a quick peek here

Well we ask the DXCore for the declaration of the Event which we are attempting to attach to like this....
-------------------------------------------------------------
Dim TheDelegate As IDelegateElement = CType(EventDec.Type.GetDeclaration, IDelegateElement)
-------------------------------------------------------------
... the iterate the parameters of said delegate duplicating the params on the method...
-------------------------------------------------------------
For Each Param As IParameterElement In TheDelegate.Parameters
    Dim NewParam As New Param(Param.Type.FullSignature, Param.Name)
    NewParam.Direction = Param.Direction
    Method.Parameters.Add(NewParam)
Next
-------------------------------------------------------------

Add Some Content
Next we need to add some default content to that Method. We have decided to continue the original plan for now, and generate a statement to Throw a NotImplementedException.

So we offload the creation of the ThrowStatement on another simple utility function just so that our code can remain tidy.

Now we could just add this ThrowStatement to our Method.
this would be done by calling...
-------------------------------------------------------------
Dim TheThrow as ThrowStatement = GetThrowStatement("System.NotImplementedException")
Method.AddNode(TheThrow)
-------------------------------------------------------------
...but We'd like to be a bit more clever with our plugin.

Although the Throw statement is a good default, in 90% of cases the first thing you'd like to do once your plugin has finished doing it's thing, is to erase the throw and replace it with something more useful.

So how about we select the ThrowStatement ready to be overtyped, just like in a template.

In order to do this you need to Wrap the code in special Template Elements. If you've every created your own templates, you'll be familiar with «Caret» and «BlockAnchor». They are placed one at either end of your code, and once "Expanded", will cause CodeRush to select the text in the document

There are 2 problems with this.

  • We don't have any code to wrap
  • We don't have any LanguageElements to represent Template Elements.

Hmmmm.....what to do?

Ok it turns out that there is a special LanguageElement for inserting arbitrary text into your code. It's called SnippetCodeElement

So the first implementation of this looked a bit like....
-------------------------------------------------------------
Method.AddNode(New SnippetCodeElement("«Caret»")
Method.AddNode(GetThrowStatement("System.NotImplementedException"))
Method.AddNode(New SnippetCodeElement("«BlockAnchor»"))
-------------------------------------------------------------
But this had the annoying side effect of inserting a CRLF after the Throw and before the «BlockAnchor». In essence the CRLF got selected as well and this just wasn't right.

So a new approach had to be found. So I asked (as I did for much of this) AlexZ (of Developer Express), if he could explain how they did this and I received and embarrassingly simple solution.

Alex suggested pre-generating the code for the ThrowStatement, deliberately removing the trailing CRLF, wrapping the resultant code in the raw Template Element text and finally adding the whole lot to the method as a single SnippetCodeElement thus...

-------------------------------------------------------------
Dim ThrowStatement As [Throw] = GetThrowStatement("System.NotImplementedException")
Dim ThrowWithoutCRLF As String = GenerateWithoutCRLF(ThrowStatement)
Dim NewSnippetCodeElement As New SnippetCodeElement("«Caret»" & ThrowWithoutCRLF & "«BlockAnchor»" & ControlChars.CrLf)
Method.AddNode(NewSnippetCodeElement)
-------------------------------------------------------------

Producing the Code
Finally we wave that "DXCore Magic Code Generation Wand" I mentioned earlier by calling...
-------------------------------------------------------------
CodeRush.Language.GenerateElement(TheMethod)
-------------------------------------------------------------
...and the inserting that code in the correct location in our original document...
-------------------------------------------------------------
CodeRush.Documents.ActiveTextDocument.ExpandText(InsertionPoint, ControlChars.CrLf & MethodCode)
-------------------------------------------------------------

And now we're done. :)

Full source is available via SVN


Updated: the previously existing repository is still intact however the code has been copied to a new repository where future work will be continued from. this new repo can be found here here

Tuesday, December 11, 2007

LanguageElements, LiteElements and IElements

It's important to understand at least 2 out of these 3 terms when creating DXCore plugins.

  • A LanguageElement is a structure that represents a code structure defined in source code.
  • A LiteElement is a Friend (Or internal) class used internally by the DXCore. It represents a code structure defined in IL (like the framework itself). This is the one you don't really need to understand because you can't cast the object itself to this type , because this type in unavailable to you, the humble plugin programmer.
  • An IElement is an interface implemented by the previous 2 structures. It provides common access to properties provided by the previous structures allowing you to code against this interface rather than have to code against the previous 2.

These 3 structures are of course the ultimate parent structures of many derivatives.

So you should write your plugin analysis code in terms of IElement derived interfaces.

Of course you'll need to create LanguageElement derived objects when you need to generate code, but try to use the interfaces for any discovery work you need to do.

If you don't do things this way, then you'll find that you need to use LanguageElements to analyse the source code and Reflection to go looking through the framework classes.

Believe me... You Don't Want To Do This!

Apart from which, using the IElement derived structures in the DXCore is way easier and results in tighter plugin code all around

A small example
So imagine that you have the code...
-------------------------------------------------------------Public Structure SomeStruct
    Private DummyMember As Integer
End Structure
Public Class SomeClass
    Private X As SomeStruct
    Private Y As Integer
End Class
-------------------------------------------------------------
The return value from GetDeclaration for X will be an "IElement" which you can cast back to "Struct" which is a descendant of LanguageElement.

The return value from GetDeclaration for Y will be an "IElement" which you can would be able to cast back to "LiteStructElement", only it's not available from outside of the StructuralParser Assembly.

Both of these can be addressed in a uniform way however, by casting them to IStructElement

Note: The theory goes that since most LanguageElement derivatives will have a matching IElement derivative. you should attempt to work in terms of IElement when trying to analyse code. Simply because you should not assume that that which you are trying to analyse is modifiable.

So hopefully that sorts out any confusion as to why IElement derivatives are used so prolifically in plugins.


Friday, December 07, 2007

Plugin Development under Vista 64-bit

There are a minor issue affecting the development of plugins under 64-bit vista.

The basic issue is that your installation of Visual studio (assuming that you go for the defaults) will be under "C:\Program Files (x86)\" and defaults in a plugin project (and indeed other types of project) will point to a directory under "C:\Program Files\".

Now CodeRush /Refactor/DXCore will all install (by default) also under "C:\Program Files (x86)\" and it seems very hard to convince the OS to allow anything else.

All this means that you will compile and build plugins to a directory ( C:\Program Files\..etc..") which the DXCore is not looking in.

The simplest way I have found to solve this is to use a program like Junction Link Magic to create a "Junction Point" between a new Empty folder created at "C:\Program Files\Developer Express Inc\" and the real folder at "C:\Program Files (x86)\Developer Express Inc\".

A "Junction Point" is a "Magic Portal" between the empty folder and the specified destination. The effect of which, is to fool the FileSystem, and hence every program that makes use of it, into seeing all the files in both locations.

It should be noted that there is only one set of files, they are just visible in 2 places. If you delete anything it will vanish from both locations

So once this is done you can happily compile Dlls to one location and run them through DXCore from the other.


CreateStubForHandler Plugin

Those who have been following this thread in the DevExpress Forums will already be aware of my involvement in a new plugin for VB developers called CreateStubForHandler

This plugin was created by Koen Hoefkens to aid VB.Net developers in their daily tasks.

The CreateStubForHandler plugin does 1 wonderful thing in 2 specific ways.

Refactoring/CodeProvider

Imagine you have this line of code...

-------------------------------------------------------------
AddHandler MyButton.Click, AddressOf MyClickHandler
-------------------------------------------------------------
...but you do not yet have and actual 'MyClickHandler'.

Typically you now have to either have a good memory for the parameters needed for the handler or you have to go trawling through the intellisense/tooltips/Object browser to determine what such a handler should look like.

Well now, with a simple refactoring (CodeProvider in Refactor3.0), you will be presented with a 'Target Picker' which you can use to determine the location that 'CreateStubForHandler' will create just such a handler.

The CodeProvider does all the heavy lifting for you. It creates the procedure and populates the signature with all the correct parameters.

It also fills the procedure with a simple throw exception statement.....
-------------------------------------------------------------
Throw New NotImplementedException()
-------------------------------------------------------------

Action

As an additional bonus, there is also an additional "Action" ("AddHandler completion") which you can map to a key of your choosing. This action should be activated when you have the following code...
-------------------------------------------------------------
AddHandler MyButton.Click
-------------------------------------------------------------
... with your caret on the right of said code. (note the lack of a comma)

Once activated, "AddHandler completion" will not only create the procedure for you but will calculate an appropriate default name for the method, but will fill out the "AddressOf" clause for you

Koen was generous enough to allow his plugin to be added to the DXCorePlugins Open Source project on GoogleCode.
So if you're interested you can get the full source to this plugin as well as a few others.

Great stuff!

Thanks Koen

Note: In truth, my only involvement in the project was a little refactoring of the code itself and the creating of a parallel VS2008 project to house the Refactor 3.0 version of the code

I have not added any functionality to the project (unless you count changing the VS2008 version to use a CodeProvider rather than a RefactoringProvider.)


Wednesday, December 05, 2007

Something, Beta, this way comes.

The 1st beta of CodeRush 3.0, Refactor 3.0 and therefore of course DXCore 3.0 is now available to subscribers of DevExpress' IDE Tools.

NOTE: These will replace version 2.x if installed and support has now been dropped entirely for VS2003 as all libraries are not build using .Net 2.0

Refactor! Vs Code!

imageRefactor has had a makeover and split it's offerings into "Refactor" items and "Code" items. At the moment, the pre-existing Refactor items are available in the Refactor! section. These are the items that take your code and reshape it, improving the readability and reusability without altering the effect it produces. image

Next up is the all new Code! section. The Code! section is for items which, unlike their Refactor siblings, do alter the code they act upon. Items like "Rotate item 90 degrees" act on some selected code and modify it in some way.  To quote Mark Miller:

'Rotate 90 Degrees' is most useful, taking logic that applies in one direction, and rotating it to apply in the other direction (converting Width to Height, X to Y, Left to Top, Right to Bottom, Column to Row, etc.), while 'Mirror Code' is less useful (converting Left to Right, "+" to "-", Top to Bottom, etc).

Other items available in Code! include the "Declare" range. These allow you to generate Classes, Structs, Interfaces, Constructors, Locals, Fields, Properties, Setters and Getters from references.

Code Issues

Refactor has always suffered from a small problem which was that you had to know that a Refactoring could be used before you could use it. So you would place your caret somewhere in code and if Refactorings were possible, then you would see the Refactoring SmartTag which lead to the SmartMenu which would then show you the refactorings that could be applied in the current location.

But if you never placed your caret in the correct location then you would have to rely on past knowledge to tell you where you might be able to refactor.

Code Issues is a promising little piece of architecture which will allow CodeRush to highlight code smells and bring to your attention, those items which could do with a little refactoring.

In the beta there are 2 Code Issues that are  highlighted. 'Undeclared Elements' and 'Unused Declarations'. This means that if you declare a variable or method but do not use it, the declaration with be highlighted and your attention drawn to it.

When I first started to use the new version of CodeRush, imageI thought I was suffering some strange programming glitch. I appeared to have some kind of imagegraphical corruption on the right hand side of my editor. It turns out that this is in fact a graphical map (see right) of the code Issues in the current document (Left).

The purpose of these would seem to be to help further draw your attention to your code issues. I have seen no sign of a Code Issues ToolWindow so far, but then this is the first beta and there are some issue preventing me at this time from accessing some of the more traditional ToolWindow. (CodeRush, Messages, Expression Lab).

As I have said there are only 2 Code Issues Providers so far but another quote from Mark Miller reveals a little about what is to come:

With regard to error checking, the goal is to ultimately implement all of the errors, warning, and hints produced by each of the language compilers we support. With regard to code smells, that's a much broader area, and for the most part we won't be talking about what we'll be addressing there until its released, other than to say that if we have a refactoring or code provider designed to solve a problem, it is highly likely that you'll see us ship a corresponding code issue provider to highlight opportunities to improve the code.

So stay tuned and I'll see what else I can find out for you.


Tuesday, December 04, 2007

My last Vista problem - Solved!

For those not keeping up... The last issue I have with Vista was detailed here.

The basic problem was that administrator programs were not recognising clicks events when they were not the foreground application.

The today I noticed, completely by accident, that My VS (a "Run as Administrator" application) DID recognise a "right click".

How strange....

That set me thinking about click messages and interception and that's when it hit me..... I run a third party App (Nifty Windows) for it's ability to toggle the StayOnTop bit of any window I choose. It does this by intercepting the Win+LClick key/Mouse event.

The problem seems to be that "Nifty Windows" intercepts the left click but is apparently (I'm guessing due to Vista security practices) is unable to send those clicks to any program which is elevated.

The solution: run Nifty Windows Elevated

Oh the relief :D


Wednesday, November 28, 2007

Extension methods and .Net 2 Revisited

It appears that, in VB, you will be unable to create the requisite Attribute unless you have "no root namespace".

Now that's annoying. All my projects have root namespaces.

If I understand things correctly the difference between C# and VB in this respect is....

...In C# this value is copied into each source file as each is created.
...In VB.Net this value is used at compile-time (and background compile-time) and every class in the system is wrapped in said namespace.

This means that a large VB.Net program is very sensitive to any changes to this particular value.

If I keep my default namespaces, then I cannot create this attribute in this namespace. I had thought I could declare the Attribute using "Namespace Global.System.Runtime.CompilerServices" but the keyword cannot be used in this way.

It looks like I will have to create a brand new project, to create a brand new dll, just so that I can put a single attribute in it.

It seems that this is another Compiler/Language deficiency for which the only answer is to create another assembly.

Perhaps I will call my new dll "System.Core.Dll" :D


A simple correction

I previously reported here, a method of using "Extension methods" in a .Net 2.0 targeted project. 

Originally I stated that the extension attribute needed to be created within the "System.ComponentModel.CompilerServices" namespace. This was incorrect and has now been corrected. the namespace in which you actually need to create said attribute is in fact "System.Runtime.CompilerServices".

Assuming that there's anybody out there actually reading any of this.......Sorry about that. I'll try to be more careful.


Wednesday, November 21, 2007

SOLVED - Multi-Target .Net 2.0 or Extension Methods

Update:Corrected "System.ComponentModel.CompilerServices" to "System.Runtime.CompilerServices"

Ok so it looks like "I was wrong". (well it's not like that hasn't happened before :))

NOTE: This information was found in an article called Basic Instincts in the November Edition of MSDN Magazine in a subsection entitled "Extension Methods in .NET Framework 2.0 Apps"

It's true that a .Net 2.0 targeted application cannot reference System.Core (The DLL that contains the Extension Attribute) but it turns out that you don't need to do this anyway.

Instead, you can create your own.

Yup with the following code.....
-------------------------------------------------------------
Namespace System.Runtime.CompilerServices
    Public Class ExtensionAttribute
        Inherits Attribute
    End Class
End Namespace
-------------------------------------------------------------
...in addition to the required import where necessary...
-------------------------------------------------------------
Imports System.Runtime.CompilerServices
-------------------------------------------------------------
...you too can fake out the IDE and have it compile your own String.ShowAsMessage Sub thus:
-------------------------------------------------------------
Public Module Ext
    <Extension()> _
    Public Sub ShowAsMessage(ByVal SomeString As String)
        MessageBox.Show(SomeString)
    End Sub
End Module
-------------------------------------------------------------
... and now you can do strange stuff like....
-------------------------------------------------------------
Call "Fred".ShowAsMessage()
-------------------------------------------------------------

The article further notes...

...this technique will not work for ASP.NET applications targeting the .NET Framework 2.0 because they have a runtime dependency on the 2.0 command-line compiler. When those apps are deployed to Web servers that only have the .NET Framework 2.0 installed, they will not work because the 2.0 VBC.EXE command-line compiler does not understand extension methods.

So I guess we just have to be careful.


Multi-Target .Net 2.0 or Extension Methods

It seems you have to choose to use VS2008 to target .Net 2.0 OR choose to use extension methods.

But you can't pick both.

ScottGu said in a comment on his blog that

Extension Methods are actually implemented entirely by the compiler - no new IL instructions within the CLR are required to support them.

This means that you can use the VS "Orcas" C# compiler and write code that uses Extension Methods, and use the multi-targetting features to run it on a vanilla .NET 2.0 box.

However the ExtensionAttribute (required to mask a method in a module as being an extension method) is not available to add to a project which targets .Net 2.0


SOLVED - COMException in VS2008 Conversion Wizard

The COMException is caused by a few projects in my solution being bound to IIS rather than to the built in Web Development Server. I Asked on the ASP.Net Forums and you can follow the conversation here.

Studio apparently needs some rights (that it doesn't get by default) to read some info from IIS.

The work around is to launch Studio with "Run as Administrator" permission and all should work as expected.

I still consider it a bug that studio doesn't explain itself properly, but this workaround will do for now.


Tuesday, November 20, 2007

COMException in VS2008 Conversion Wizard

The first serious project I am undertaking in VS2008 has stalled at the first hurdle.

I am attempting to upgrade a VS2005 Solution to VS2008.

This particular solution has approximately 15 projects, with 5 being WebApps.

When I open this solution in VS2008 and allow the Wizard to do it's thing, It fails on 3 of the 5 WebProjects with COMException. and nothing else.

Not the best error information.

Any thoughts?


[Update: I just realized that I had no pointer to my eventual solution.]

Monday, November 19, 2007

Whatever you do DON'T Download VS2008 PRO!..

...for at least the next 4 hours. I needs to get me a copy of this and I don't need the rest of you hogging all the bandwidth :P


VS2008 - Available to MSDN now!?

Well Daniel Moth thinks it is in his post here.

I can't see it though :(

Must mean it won't be long though :D


Beta 2 of VS2008 no longer available.

That's right Beta2 of VS2008 seems to have mysteriously disappeared from MSDN subscriptions :)


Sunday, November 18, 2007

Refactoring vs Simple Code Transformation

After conversing with Trevor about the inner working of duplicate line, and a retelling of my understanding of said feature here, I have found myself wondering about a potential new feature.

Duplicate line is an interesting feature which takes advantage of RegEx to match expressions to code and then create further code based on the original code.

The self-defined purpose of "Duplicate Line" is to duplicate the line on which the caret resides.
-------------------------------------------------------------
Side-Note: I have a suggestion, registered here, which suggests that it would be useful to invoke duplicate line retroactively, when one's caret resided already on a blank line and one wished to insert a duplicate of the line above.
-------------------------------------------------------------
To this end, the 'create' pattern (RegEx) is largely the same as the 'match' pattern.

But is there any reason that they should be?

Well yes... for 'duplicate line'.... they should be, but what about some other function (from here referred to as 'code-transform') which we could activate manually in the same way and have the system match the preceding line of code and transform it into something else.

Perhaps said feature could even popup a list of named patterns which it was felt matched the current situation so that the user could pick the most appropriate one.

Does this sound familiar? Yes of course it does. It's RefactorPro isn't it?.

So why re-invent the (extremely streamlined, dead flashy and effective) wheel?

Well to be honest, I'm really not sure. My mind, like this post, started from 'Duplicate Line' and wandered away with itself from there.

I guess the difference is in how you create new "Code-Transforms" vs "Refactorings"

Refactorings are probably way more sophisticated and clever due to having a rather clever understanding of the code upon which they operate. But then again you do need to write a new piece of code for each one you create. There's the hassle of creating a new project, a new plugin, a new Refactoring and handling various events.

On the other hand, one might create a more basic type of code-transformation simply by setting up a few RegEx expressions.

This is theoretically made even easier by the existence of the DXCore's RegEx Aliasing System

So now Imagine that we have this new Code-Transform Action. We've hijacked the Ctrl+T keystroke and bound it to "Code-Transform" and we come across the following minor code...
-------------------------------------------------------------
Dim SC As New SomeClass
-------------------------------------------------------------
...which for reasons of taste and style (or lack thereof) we decide we would like to rewrite as...
-------------------------------------------------------------
Dim SC As SomeClass = New SomeClass
-------------------------------------------------------------
Well in exactly the same way as 'Duplicate line' works, you can create a match pattern...
-------------------------------------------------------------
%Dim1%%Identifier1%%mws1%%Initialization1%? %EndOfLineComment1%?
-------------------------------------------------------------
...and a replace pattern...
-------------------------------------------------------------
%Dim1%%Identifier1%%mws1%%As1%%Type1%%Initialization1%? %EndOfLineComment1%?
-------------------------------------------------------------
... and this when triggered, would introduce the extra code needed to Refactor our simple example.

Of course the reverse could easily be performed as well by simply reversing the RegEx's in another "code-transform"

There are limitations to this simplistic system. Off the top of my head I can think of "single line only Refactoring", (and therefore) transformations cannot affect code-blocks (Loops).

but there might be some merit to this idea.

What do you think? All comments/thoughts appreciated


Cheatsheet 1 - RegEx Expressions

This post is more for myself than for anything else. It is to remind me of the location of a good cheatsheet for Regular expressions

Held at http://regexlib.com/CheatSheet.aspx


Duplicate line - How does it work?

Note: Information in this post is based entirely on observation. It contains no insider knowledge whatsoever.

So how does it work? Well..."Duplicate line" doesn't strictly duplicate the line. It creates a transformation of a copy of the line and then expands the transformation into a new line underneath the original.

So why does it do that? Wouldn't it be simpler to just copy the line of code?

Well yes but then again, how useful would that really be?

You'd have an exact copy of the line you already had. But then typically you don't want an exact copy of the code. You typically want a version which is slightly different.

For example you might want to duplicate a variable declaration but then change the name of the variable which is being declared. Or perhaps duplicate a method call but then alter the parameters that are passed.

In these cases it is better for CodeRush to help you out by setting up which part of the new code is selected and placing field wrappers around other selected bits.

And this is what it does.

It can do this because of several pre-setup rules each comprising a pattern to match code and another to construct code.

Thus a match pattern of...
-------------------------------------------------------------
%SubOrFunction1%%Identifier1% \( %ParamsDec1%? \) (%As1%%Type1%)? %EndOfLineComment1%?
-------------------------------------------------------------
...together with a Create pattern of ...
-------------------------------------------------------------
%SubOrFunction1%«BlockAnchor»%Identifier1%«Cursor» ( %ParamsDec1% ) %As1%%Type1% %EndOfLineComment1%
-------------------------------------------------------------
...allows us to duplicate...
-------------------------------------------------------------
Dim SomeVar as Integer
-------------------------------------------------------------
... and have CodeRush immediately highlight "SomeVar" in the duplicate ready for replacement.


Tuesday, November 13, 2007

Behavior in Vista Newsgroup

Sometimes I discuss (have a blazing row with) my father about all sorts of things. We each explain (at great volume) our points of view to the other hoping to persuade them (by beating any given point to death) that our view is the more accurate.

Observers of this behavior will wonder if they shouldn't move the sharp objects out of the room. Just to be on the safe side.

But the truth is that my father and I have the greatest respect for one another.
We can just be very bad at listening to one another. :)

Whilst looking for a suitable newsgroup in order to post about my Vista problem I came across microsoft.public.windows.vista.general.

I posted about my problem and went about my business. I had naturally added this newsgroup to my newsreader Omea Pro, so when I was informed by said reader that an absolute torrent of posts had appeared in said newsgroup, my interest was of course piqued.

I clicked the folder and started to read the titles of the posts hoping for some response to mine.

I'm afraid that I have to report, to those of you lucky enough not to already know, that the 5 year olds have taken over this newsgroup.

There are some valid informative posts in this newsgroup, but they are largely hidden, for the moment at least, by the relative avalanche of "alternative" posts wherein the correspondents have long forgotten any actual facts that their arguments might have been based on, and settled instead upon the time honored strategy of name-calling.

The signal:noise ratio is approx 10-15:1

Wow that's a lot of Crap. Do these people really have nothing better to do that to "virtually" shout names at one another across the ether can they really maintain this constant level of bickering about nothing.

My 2 eldest children are rather adept at fighting in that way that siblings will do about almost anything. But even they eventually get bored and give up.

I hope that I never reach the stage where reasoned argument is forsaken and personal flaming rapidly becomes the default strategy.

I think I'm going to start listening to my father a little more.


Vista Ultimate, 64-bit, VS2005, "Run as Administrator"

As the title suggests I run Vista 64-bit (at least at work). I have a core2duo something or other and a whopping 4Gig of RAM.

I run VS2005 (although I think I may be switching very soon :P). and it runs very well apart from one thing.

I can't switch to it.

Well that may be over-exaggerating things a little.

I can switch to it...using Alt tab
I can switch to it...using the task-bar
I can switch to it...sometimes....by clicking on it when it's in the background.

but I can't switch to it when I click on it in the background and I'm not already running a UAC elevated process.

Yes that's right, it's as if the Elevated  processes all run in a different desktop all the time.   There's no grayed out background. there's no prompt asking me if I want to allow this action.

But none the less I cannot switch from notepad to VS2005 by clicking on VS2005 in the background of Notepad.

Now I do run VS2005 elevated as Administrator, because encourages me to every time it loads by showing me this screenimage

Why I continue to have it show the message, I don't know. I thought it might go away once I told the .exe to "Run as Administrator" every time it loads. But no, this does not appear to be the case.

I have installed VS2005 SP1 and I have applied the Vista update for same.

However... I'm not yet been 100% totally forthcoming with the full facts.... You see... It's not just VS2005 that is doing this to me.

There's another culprit and It's none other than IIS7.

So with this baffling combination of circumstances, can someone somewhere tell me what's going on here and how I can fix it.

I would love to imagine that this will be fixed in a matter of weeks when I install VS2008, but I doubt it.

 

So how's about it... anyone... anyone at all?


The time has come.... VS2003... you're fired.

Ok sure that was cheesy, but come on..... Just read the title again. it said "VS2003". This is a product whose name at least is soon to be out of date by 5 years. (ok nobody say XP)

I'm just sick of maintaining code that's just that old. (ok nobody say VB6)

The time has come. I am mere days now from the rollout of the last of our products to be upgraded from using version 1.1 of the .Net framework to version 2.0.

And not a minute too soon because version 3.0 is already out and version 3.5 is due out before the end of this month.

It is my sad (ecstatically happy really) duty to inform you that VS2003 is finally on it's way out. And to that end I must further inform the populace at large (or small in the case of the readership of this blog) that I will no longer be allowing said framework to hold back any of my plugins either.

I have a reasonably new core2duo 64-bit machine with 4 Gigs of ram running vista ultimate 64-bit. and I don't mean to sully (no Mulder or X-Files jokes allowed) it with any of that .Net 1.1 crap (ok no Vista cracks either).

I will be moving all plugins that are deemed worthy, to version 2.0 or better of the framework just as soon as I can find the time. (yeah I know... that could lengthen their lives by years)

I will attempt to mark their source in Subversion in such a way as to allow the 1.1 versions to live on in some sense but that's about it.

VS2005... My mate multi-targeting says your days are seriously numbered.

But VS2003 and  .Net 1.1...... You're fired.


A nice stress-free holiday.

Yup that was the plan..

And to be fair it was quite a stress-free holiday. The journey home and the subsequent few days were a little more tense.

You see the idea was that given our tight financial situation we would not be going abroad or holidaying in any official location. We would instead holiday by taking a break from the norm. We would put ourselves beyond the reach of the Internet.

This is a big step as, for my wife (Anne) and I, the computers have largely replaced the television as our primary indoor (non adult-themmed) entertainment.

We live on the south coast of England and so we don't get to see my Anne's family very much. (Like all families it should be understood that for some members this is a good thing and for others it is not so good.) So we planned to spend the first few days of our break, visiting with her family "Up North" in Halifax.

This is a journey of some 286 miles which Google maps informs me should have taken roughly 5 hours. The route I took was about 20 miles more than this but took about the same time. All told, including numerous toilet and food breaks, we took about 6.5 hours to do this trip in the northward direction.

Once arrived we spent a pleasant couple of days in the company of Anne's Parents, Sister, Niece and their respective families. A good time was had and we managed to get off pretty lightly when it came to holiday junk acquired. I even managed to get the car's M.O.T (Mandatory, once yearly, minimum roadworthiness check here in the UK) renewed whilst everyone else generally wandered around the shops looking for holiday junk to fill the car with.

And so came the time of the return journey.

The car was packed, the kids were packed and some holiday junk was packed. We drove around the area passing at each family home to say goodbye and then we were off.

I think it was around 7pm on Tuesday evening. [This time was chosen, in theory to be good for getting the kids to sleep at given that it is their usual bed time. And even those of you with no kids whatsoever should appreciate that it is far less stressful to travel with kids who are unconscious than with kids who are constantly talking: I'm hungry", "I'm Thirsty", " I need the toilet", "Are we nearly there yet?". And this can all be in the first 10 minutes.] We set of at a fair pace (Breaking no speed limits or other sensible driving guidelines at all. Honest) and covered what I thought to be a fair distance. Google says it was about 112 miles in 2 hours. [I dispute this and suggest it was more like 100 but who am I to argue with the great Google :)]

It was at this point that things started to take a turn for the worse. We suddenly noticed a suspicious-looking light on the dashboard. It looked like an engine with little lightning strike through it. Then it disappeared. A minute later it was back again. A minute late it was gone again.

We got a little worried and stopped the car at the nearest service station to have a look. We stopped the car opened the bonnet (That's what we call the hood for any Americans out there:) ) and I used my considerable "mechanical engineering skillz" to confirm for my wife that yes indeed, we still had an engine and no it did not appear to have been struck by lightning.

Happy with my conclusion I suggested that not would be a good time to get everyone out of the car and feed and water the family. This seemed good because it would be a break on my terms rather than on those of my children. So we trooped into the service station (Kids in PJs and everything) for some food.

Food was (for a change) not bad and everybody felt better. Everybody got back in the car and we noted with optimism that the warning light was now out and all seemed normal.

Back on the road and a few miles further on we saw a different warning light come on. You should have figured out by now that I know diddly about cars and so this time we looked in the manual to find out what was happening.

The light said the manual indicates the failure of the automatic transmission. (Auto-Gearbox for those, like me, who would have had to ask their wives what this meant).

It then went on to say that since the automatic gears we're knackered, that we should shift manually instead. Well that seemed fair enough. I assumed (and you know what they say about assumptions) that we could get away with this until we could call a mechanic at home.

So instead of leaving the car in D(Drive) we now have to switch from 1 through 3 appropriately. Fine we can do that. I learned and am licensed in a manual so these concepts are now new to me even if doing so in an automatic is a little strange for me.

So we continue a little further.... and then Anne points out that although this light is still on, the rest of the dashboard has gone dark.... a moment later a seatbelt warning light had come on. Suddenly Anne, who is driving, says she thinks the car is loosing power. Literally she is having to push the accelerator further to get any kind of momentum from the engine.

The car is indeed losing power so we decided (rather quickly that the car was about to die on us and perhaps the middle lane (out of a possible 3) on the M1 (major motorway/Highway running North-South) was not the best place for this to happen. Especially at about 21:30 at night in reasonably high traffic.

So as quick as we can we get into the left-most lane (the slow lane) where we noticed signs indicating that we were just about to hit the off ramp to another service station. This would be a very good place to stop so we indicated and drifted left in to what we thought was the off ramp but turned out to be just the hard-shoulder (no idea if those outside the UK have another term for this but it's a lane to the left of the slow lane used in case of emergency) we quickly realized our mistake as it seemed that if we continued in this lane we were going to hit a bridge. Not good. We indicated and drove back out onto the slow lane, drove another 10 yards or so and my wife declared that all power seemed to have disappeared. Having already passed the bridge, we steered left again onto the hard shoulder and to our relief saw that this was indeed the off-ramp. However, having no power save for the momentum already ours, we saw that we would not reach the service station and so steered (For by not it's not really driving, there being no drive) onto the true hard shoulder where the car was brought (more from lack of power than from applied brakes) to a halt.

So 21:30ish at night, it's dark and it's cold but there's a service station within sight. My 3 kids Molly(5), Daniel(4) and Rosie(1) year old are asleep on the back seat of the car but we're still technically on a motorway. This is not a safe position to be in. It is not a happy position to be in. I could carry the elder 2 kids if need be and Anne could carry Rosie easily enough but I wasn't happy about the idea of walking any length of road in the dark under those conditions.

We quickly decided that we couldn't stay here as it was possible we could get hit by some fool driver at any moment. Then we noticed that the Hazard lights (emergency lights on the car) which we had remembered to turn on, were not working any more. The headlights had also failed. At this point I was not thinking much of that M.O.T I had had done.

So that did it. It's bad enough being in a broken down car at the side of the motorway at night in the rain (Did I mention the rain).

But now the car has lost all electrical power including anything that might power the Hazard lights. We had to get out.

Just then we noticed some blue flashing lights ahead. It seems that some police had just driven past on patrol and had seen the car. The offered to give us a lift to the service station. It took some doing to rouse my 2 eldest but once their subconscious minds were vaguely aware of getting to ride in a police car, the woke up with amazing speed. The Police dropped us off at the service Station and said they would call Highway maintenance or some such group who would help me get my car towed off the motorway. I booked the family into a room for the night after all who knew how long it might take to get this all sorted. Then I resolved to go back to the car to get some blankets and nappies (diapers) and anything else which might have been considered essential.

I took a safe(ish) route going outside of the barriers that a car might potentially have hit, thus affording me some protection. I reached the car and opened it up. I realized that since nothing was functioning anyway, I might as well turn everything off. Off went the headlights, the hazards and the heater. I shut the car and went to the boot (trunk for my American friends) to retrieve the bits for Rosie. Having got these I decided it would be good since I was here already to pick something up to occupy my kids, as sleep was not going to be foremost in their little heads after something like a ride in a police car. So I went to open the car up (meaning to retrieve some picture books or toys or something) and discovered that now the central locking mechanism of the car had decided to give out.In and of itself I could understand this as I can see where electrical power would help this subsystem in it's duties. but what I don't understand is why I couldn't even turn the key to unlock the passenger door itself. Strange. I resolved to figure this out later. I had already got my hands on the vitals necessary for looking after my Rosie.

On the way back I my mobile phone began to ring. It was the Highway guys. they informed me that I could not leave the car where it was and that I would have to move it or they have the police do it for me at a probable cost of over £100. This, I thought, was a little steep and resolved to find a way to do it myself.

Since I had to yet phoned and kind of rescue service, being of mind to sort my family out first I realized that no rescue service would arrive in time to move the car before the highway guys got the police to do it. So I asked the guy on the phone (James  I think his name was) Where exactly was the car felt to be safe?

James indicated that basically it was unsafe as long as it was on the motorway so as long as I got it off there, it would be ok. I looked at where the car was and wondered if I could push it off. however as I looked closer, I realized that in order to get the car into the car park I would have to cross back on to the exit ramp from the hard shoulder. this would be like pushing the car into traffic, and without any lights of any kind this was really not going to be a valid option.

Then I spotted the "End of motorway regulations" sign. It stood a full car length from one end of the Hard shoulder providing the perfect place where the car could reside without being either in the car park or technically on the motorway. I solicited help from a guy playing the slots in the service station, and together we approached the car, the battery of which, had now managed to store enough energy to allow reentry into the ca. I disengaged the gears putting the car in neutral, removed the handbrake and we managed to push the car the length of the hard shoulder to it's new "safe" location. I never did ask the name of the guy who helped me push the car but I slipped him the close to £5 loose change I had in hopes that it might help him to his fortune on the slots.

A short while after this, I got a call from the highway guys saying that the police had seen the car and were prepared to tow it around the corner into the car park for me (at no charge). I was very glad to hear this as I was still very unsure if where I had left the car would be acceptable.

The towing complete, I was off back to the room I'd booked for the family where I found mum looking ragged. This is not a reflection on here, but more on the behavior of my elder kids who seemed to have picked up the same levels of energy as they might have gained from several energy drinks mixed with some sort of neat sugar IV and they were using this burst of energy to pound on one another. This coupled with cries of Rosie who apparently needed changing meant that my arrival was greeted with much anticipation.

A little while later we had managed to get all 3 children to sleep the 2 eldest had fought so much that they now had each a bed of their own, and Rosie had a makeshift bed made out of a much folded blanket. I was preparing to sleep on the floor but Anne convinced me that we could now move Molly back into the same bed as Daniel. After this we both collapsed into bed where we slept very soundly until morning.

In the morning we called the AA who showed up very quickly and told us that our alternator was shot and a replacement would cost us about £90. Well we paid up and the car was fixed up right there in the car park.

A day later the fan belt fell apart. It was literally shredded.

We got that replaced and now the Power steering pump is leaking. We have a replacement for that and it's being fitted tomorrow morning by a friend of ours.

I think the car is fast earning a nickname of "The money pit"

I'm glad I cycle to work :)


Monday, November 12, 2007

Duplicate Line - Simple Examples

'Duplicate Line' is a simple enough concept....

  • Type a qualifying line of code.
  • Hit <Shift>+<Enter> instead of <Enter>

CodeRush will intelligently duplicate the line of code.

What do I mean by 'intelligently duplicate'.

Well I assume you know what I mean by 'duplicate'. What I mean by 'intelligently' is probably best demonstrated rather than explained.

Suppose I have the VB.Net line...
ImportsSystemData 
Position your caret at the end of this line and hit <Shift>+<Enter>.
CodeRush duplicates the line in question.....
ImportsSystemDataSelected ...and then positions the selection block cleverly around the namespace itself so that you can over-type with an alternative.

Similarly you can use this to create a whole slew of variables of the same type.....

PrinvateAAsInteger

...becomes...Private2Vars

 

 

...becomes...

PrivateManyVars

 

 

 

 

I think you'll agree, this is quite the handy function.


Selection-Inversion

Selection-Inversion (CTRL-SHIFT-I) is a mechanism for transforming one simple code structure into another or back again.
For example:

From .... "X = True" ....into.... "X = False"

..OR..

From .... "A = B" ....into.... "B = A"

So how does this work?

We it's all down to pattern matching and the wonderful alias engine provided by DevExpress.

Each Selection-Inversion requires a pattern to match and another pattern to replace.

The expressions that allow the above Inversions are simple in nature and, unlike most regular expressions, quite readable.

For example, the first Selection-Inversion above matches using...
-------------------------------------------------------------
%Identifier1% = %BooleanValue1% %EndOfLineComment1%?
-------------------------------------------------------------
...and replaces with...
-------------------------------------------------------------
%Identifier1% = «?InvertBoolean(%BooleanValue1%)» %EndOfLineComment1%
-------------------------------------------------------------
This shows an additional strength of Selection-Inversion. That of the StringProviders. I'll cover StringProviders in another post but as you can see from this small example. a StringProvider is essentially like a function which takes 0 or more parameters and returns a string. A very simple idea but one which allows for a lot of customization.

The example here uses an "InvertBoolean" StringProvider which, as it's name suggests, inverts the passed boolean and passes out the text which represents it's opposing value.

The second example matches using...
-------------------------------------------------------------
%Identifier1% = %Identifier2% %EndOfLineComment1%?
-------------------------------------------------------------
...and replaces with...
-------------------------------------------------------------
%Identifier2% = %Identifier1% %EndOfLineComment1%
-------------------------------------------------------------

Note the subtle change here. Only the numerals 1 and 2 have switched positions. The numerals can be tacked on to any alias and allow each alias type to be used multiple times in the match string and then placed in arbitrary positions in the replacement string.

As you can see the Selection-Inversion is quite powerful.

There are also a few more Inversions in the shipping version of CodeRush which deal with inverting loops so that they progress in the opposite direction from which they started but I'll leave these for you to investigate.


Sunday, October 28, 2007

BST - Bites me again

I don't know what it is that make this happen every year.

But every single time that the clocks have to be adjusted due to either the start or the end of BST, I inevitably find out about it at around midday on the Sunday on which the change occurs.

I therefore, am either late for some appointment, or alternatively miss that all important extra hour in bed.

Of course I could simply go to bed an hour earlier this evening, but frankly it's been a week since I touched a computer so if you think I'm gonna leave this one early his evening you've got another thing coming.

:)


Friday, October 19, 2007

Holiday???... What's that then?

The trouble with working for yourself (or family in my case) is that you very rarely get to take any official time off.

Not withstanding the birth of my last child Rosie, I haven't taken "official holiday" in about 3 years.

But I'm taking next week off to chill with a few good books.

Money is a bit tight so my wife, my 3 kids and myself are going to visit my in-laws (Just for a few days) who don't really know what the Internet is, much less have a computer.

I'm leaving my laptop behind and I'll probably switch off my mobile phone.

I might take a pen and paper but that's the technological limit.

The pace of life is going to slow to a snail pace and I might finally be able to relax for a bit :)

Of course we'll be staying with the in-laws so there's no guarantees :)

So this is me dutifully giving notice that my DX-Squad presence is going to lapse like never before.

So to anyone who emails me during the next week.... replies will be a little delayed. :P

Tuesday, October 09, 2007

Aliases - The art of readable regular expressions

Here's a simple question.. Which of these is more readable?

  • (\.?((\[(([A-Z]|[a-z]|([À-Ö]|[Ø-ö]|[ø-É™]))|_)
    ((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]|[ø-É™]))|_)|[0-9])*
    (\u0025|&|@|!|#|\$)?\])|(([A-Z]|[a-z]|([À-Ö]|[Ø-ö]
    |[ø-É™]))|_)((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]|[ø-É™]))|_)
    |[0-9])*(\u0025|&|@|!|#|\$)?)((\s*)\.(\s*)((\[(([A-Z]|[a-z]|([À-Ö]
    |[Ø-ö]|[ø-É™]))|_)((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]
    |[ø-É™]))|_)|[0-9])*(\u0025|&|@|!|#|\$)?\])|(([A-Z]|[a-z]|([À-Ö]
    |[Ø-ö]|[ø-É™]))|_)((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]
    |[ø-É™]))|_)|[0-9])*(\u0025|&|@|!|#|\$)?))*)


  • %Identifier%


I'll give you a minute to let that sink in......


The 2 expressions above are both valid and equivalent in DXCore's 'Alias' subsystem. The 'alias' subsystem backs the 'Duplicate Line', 'Selection Inversion" and "Intelligent Paste" functions of CodeRush.


Which would you rather type?


The 'Alias' subsystem is a very simple but very powerful recursive substitution system which starts with a simple phrase. (In this case %Identifier%) and then expands it according to 1 or more rules. The resultant phrase is then analyzed and, if capable, expanded again... and again ... and again.


%Identifier%

...becomes...

(\.?%SimpleIdentifier% (%ws%\.%ws%%SimpleIdentifier%)*)

...becomes...

(\.?(%EscapedIdentifier%|%NonEscapedIdentifier%) (%ws%\.%ws%(%EscapedIdentifier%|%NonEscapedIdentifier%))*)

...becomes...

(\.?((\[%AlphaOrUnderline%%PartialIdentifier%%TypeCharacter%?\]) |%AlphaOrUnderline%%PartialIdentifier%%TypeCharacter%?) (%ws%\.%ws%((\[%AlphaOrUnderline%%PartialIdentifier%%TypeCharacter%?\]) |%AlphaOrUnderline%%PartialIdentifier%%TypeCharacter%?))*)

A few rounds later and we have our full expansion....


(\.?((\[(([A-Z]|[a-z]|([À-Ö]|[Ø-ö]|[ø-É™]))|_)
((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]|[ø-É™]))|_)|[0-9])*
(\u0025|&|@|!|#|\$)?\])|(([A-Z]|[a-z]|([À-Ö]|[Ø-ö]
|[ø-É™]))|_)((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]|[ø-É™]))|_)
|[0-9])*(\u0025|&|@|!|#|\$)?)((\s*)\.(\s*)((\[(([A-Z]|[a-z]|([À-Ö]
|[Ø-ö]|[ø-É™]))|_)((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]
|[ø-É™]))|_)|[0-9])*(\u0025|&|@|!|#|\$)?\])|(([A-Z]|[a-z]|([À-Ö]
|[Ø-ö]|[ø-É™]))|_)((([A-Z]|[a-z]|([À-Ö]|[Ø-ö]
|[ø-É™]))|_)|[0-9])*(\u0025|&|@|!|#|\$)?))*)


At each round of the substitution you can see the power of  Aliasing (not to mention the pre-built list of aliases) at work.


And what a list it is..... 93 separate pre-built aliases found in the "Core\Aliases\Regular Expressions\System" section of the DXCore options.


If  you find, somehow, that these aren't enough you can create you own. DevExpress have even allocated a place for you to do just this in "Core\Aliases\Regular Expressions\User"


But it doesn't stop there. Each defined alias can be referenced either on it's own, or with a numeral suffix from 1 to 9. Thus you can have %Identifier%, %Identifier1%, %Identifier2% .. all the way through to .. %Identifier9% all used in the same expression.


This paves the way for some pretty powerful features


In my next couple of posts I'll show you how we take advantage of aliases in our use of "Duplicate Line", "Smart Paste" and "Selection Inversion".


Thursday, September 27, 2007

Trevor is unlocked

Trevor W is blogging. Take a look over at http://trevorunlocked.blogspot.com
Trevor W has unlocked his brain and will shortly be pouring forth the cream of the content from within. Available at http://trevorw.blogspot.com, Trevor is well versed in many technologies available from DeveloperExpress and is particularly keen on their XPO and XAF technologies and we should begin to see the gems of information pour forth soon.

Well done Trevor....

I have a feeling I'll be reading your blog for some time to come.

Friday, September 14, 2007

DX_Contrib, MoveIt, PaintIt and UnusedVariables all added to DXCorePlugins

The sourcecode to DX_Contrib, MoveIt, PaintIt and UnusedVariables has now been uploaded to http://DXCoreplugins.GoogleCode.com
These projects (DX_Contrib, MoveIt, PaintIt and UnusedVariables) are all still somewhat in flux.

I'm trying to get around to making sure that the cache employed by each of them for paint purposes is kept up to date.

This seemed originally to have some performance issues and I am trying to move towards a background threaded mechanism for keeping said cache up to date.

The problem seems to be that each time I approach this system looking to see if I Can improve it, it takes almost all my spare time to analyse what I have done to date. so that I seem to have very little time left to actually improve it.

This of course smacks of poor documentation/commenting. Therefore I have checked the entire set of projects into GoogleCode.com.

At least this way everyone can see where things have reached.

I am by no means giving up on these projects though. I intend to start going through the code making damn sure that I comment things as I go this time ;)

New project: DX_Sample

I have added DX_Samples to http://dxcoreplugins.googlecode.com.

DX_Samples was created in response to a question on the DX_Plugin newsgroup asking for
"a quick example of how I might go making an action that auto-creates regions around any properties that are not already in a region."

DX_Samples contains a plugin called RegionWrapProperties which wraps *all* properties in a class in a region. This is clearly not *exactly* what the original poster asked but we'll get there.

In the mean time we now have a suitable project for creating reference examples about how things can be done, without necessarily needing to create *full* examples.

Wednesday, September 12, 2007

Coderush EmbedParenthesis Tip

Idea by Neal Culiner... Configuration workaround by Mark Miller....
Coderush contains a feature called "Embed Parenthesis". this feature allows a user to select a portion of their code and to then type either '(' or ')'.

At 19:20 this evening (According to my newsreader) Neal Culiner suggested on the Coderush forum that it would be good if the existing EmbedParenthesis feature could be made somewhat more intelligent. He suggested that the caret should be placed either left or right of the final expression dependant on which of the 2 keys had been pressed in order to activate said function.
-------------------------------------------------------------
Note:
This is particularly useful as, Neal pointed out, for vb programmers who regularly highlight small expressions and wrap parenthesis around them so that we might CInt, CStr or CType.

I would also be sensible to use this to wrap an expression in any function call which passes such an expression.
-------------------------------------------------------------

"Great" said I "Add that to the support center and I'll track it too".

By 20:20 Mark Miller had spotted the conversation and posted a solution which required no new distribution of Coderush as all could be done with the existing version.

For those not willing to click through and read Mark's version, the solution is simple and elegant.
Simply create 2 'Selection\Embedding' entries. One for ParensCaretOnLeft and another for ParensCaretOnRight. Each should be the 5th type of SelectionEmbedding

For ParensCaretOnLeft, the Top line should be...
-------------------------------------------------------------
«Caret»(
-------------------------------------------------------------
...and the bottom line should be...
-------------------------------------------------------------
)
-------------------------------------------------------------

This should be suitably changed for ParensCaretOnRight

Then just change the existing bindings for Shift+9 and Shift+0 in "IDE\Shortcuts" to trigger the "Embed" rather than "EmbedParenthesis" and give each a parameter of either
'ParensCaretOnLeft' or 'ParensCaretOnRight'

You should now be good to go.



Tuesday, September 11, 2007

Write your own Dynamic Template

How do you write your own custom Dynamic-Template for CodeRush?
CodeRush 2.0 introduced the concept of Dynamic-Templates which I blogged about some time ago here. However I don't think I ever went into any detail about how you make your own.

Well the process is fairly simple.

To show you how this is done I will give an example.

Lets create a new template that will spit out code like...
-------------------------------------------------------------
Throw New ApplicationException
-------------------------------------------------------------
OR
-------------------------------------------------------------
Throw New System.InvalidCastException
-------------------------------------------------------------
OR
-------------------------------------------------------------
Throw New System.IO.FileNotFoundException
-------------------------------------------------------------

...based the specifics of your mneumonic.

The first step is to create a Dynamic List.

Follow these steps to get to the Dynamic Lists options page:

-------------------------------------------------------------
1. From the DevExpress menu, select "Options...".
2. In the tree view on the left, navigate to this folder:

Core

3. Select the "Dynamic Lists" options page.
-------------------------------------------------------------

Now we would like to create a "neutral" list, because this list should be available to all language types.

(Note: This is not technically true. I would prefer to make this list available to only VB.net and C#, but for now there is no way to do this other than to duplicate the list for these types. This will not matter too much as we will only be creating templates that use this list in VB.Net and C# anyway)

To do this we must ensure that the language dropdown reads "neutral".

Next we will right click the "Lists" list in the center column of the options screen and select "New".

You will next have to fill out 3 boxes with values for Name, Variable and a Comment.

Name should mean something to you, and it is what will appear in the previously mentioned "Lists" list once you save. I typed "Exception Types" in this box.
Variable is the suitable variable name in which DXCore will store the user/developer's selected item. I typed "Exception" here.

...and Comment is just a comment. I guess you should write a comment here :)

Once saved, your list is ready to be filled. This is accomplished by adding items on the right-hand side of the options dialog.

Each item added requires a mnemonic and a value.
We will add the following items

a - ApplicationException
ic - InvalidCastException
fnf - FileNotFoundException

Then we can push "apply" and our list is saved.

So how do we use this list in a sensible way?

This is the easy part.

Navigate to the "Editor\Templates" options page and create a new template. I'm going to do the VB one for now so I'll select VB.Net from the language dropdown first.

This template will need a special name. You need to use a special syntax within the name to indicate where DXCore should allow the user to substitute one of the mneumonics we created earlier.

We will call our Template "tn?Exception?".

What this means is that our Template will be triggered by the letters 't' , 'n' and any mneumonic from the Dynamic-List.

The expansion of our template will be:-
-------------------------------------------------------------
Throw New «?Get(Exception)»
-------------------------------------------------------------
The '«?Get»' is a StringProvider. StringProviders are available to insert from the right-click context menu in the expansion box. The '(Exception)' is the parameter for the StringProvider. In this case the phrase '«?Get(Exception)»' retrieves the string held in the "Exception" variable placed there by the trigger mneumonic.

Once this little gem is saved, you should be able to trigger your 3 expansions with any of the 3 phrases 'tna', 'tnfnf' or 'tnic'

The great thing is that you can add additional exception types to the "Exception Types" Dynamic-List at any time and they will also work with the template we have defined.

So now you have some simple mneumonics to help throw exceptions.

Sunday, September 09, 2007

Minor CR_WorkBench update.

CR_Workbench now Autoloads and Autosaves.
Yes CR_WorkBench now has an option "AutoLoad and AutoSave" vailable from "DevExpress\Options\ToolWindows\WorkBench".
This will cause your WorkBench to save each time you close your solution.
It will (kinda obviously) attempt to load a WorkBench each time you open a solution.

This new functionality added in revision 18 of DXCorePlugins

Wednesday, September 05, 2007

URL Mistake

It seems I have been quoting the wrong Urls in my previous DXCorePlugin posts.
I have now corrected the posts themselves but if you use an rss reader to view this then you might have already downloaded an earlier version.

Essentially I published Urls which required a login in order to gain access the the resources.

The correct Urls are
http://dxcoreplugins.googlecode.com/svn/trunk/CR_Contexts
http://dxcoreplugins.googlecode.com/svn/trunk/QuickTemplates
http://dxcoreplugins.googlecode.com/svn/trunk/CR_WorkBench
http://dxcoreplugins.googlecode.com/svn/trunk/Common

CR_Contexts added to DXCorePlugins

I have added a new plugin (CR_Contexts) to DXCorePlugins to add a few new contexts to DevExpress's IDE Tools

The new plugin provides 3 new Clipboard contexts called 'Clipboard Contains (Literal)', 'isMultiLine' and 'Clipboard Contains (RegEx)'

All found underneath 'Editor\Clipboard'

Enjoy.

This source available via GoogleCode and Subversion.
CR_Contexts available from http://dxcoreplugins.googlecode.com/svn/trunk/CR_Contexts
Common code available from http://dxcoreplugins.googlecode.com/svn/trunk/Common

QuickTemplates added to DXCorePlugins

Just a quick note to tell those who are interested that I have added my QuickTemplates plugin to DXCorePlugins
Yup, QuickTemplates is now available as a part of DXCorePlugins.

This source available via GoogleCode and Subversion.
QuickTemplates available from http://dxcoreplugins.googlecode.com/svn/trunk/QuickTemplates
Common code available from http://dxcoreplugins.googlecode.com/svn/trunk/Common

CR_WorkBench

CR_Workbench is a DXCore plugin which provides you with a toolwindow to store references to commonly used files.

CR_workBench gives you a toolwindow into which you can drag/drop files from either Solution Explorer or Windows Explorer.

All files placed on the WorkBench can be Double-Clicked to load them into the editor

The WorkBench has a context menu which allows loading and saving it's list to and from a file called [Docs and Settings]\[You user name]\Local Settings\Application Data\WorkBenches\[Solution Name].sln.wrk"

The only real point is to allow you a window which does not contain the whole breadth of files in your solution. If you save your workspace (I'm thinking of adding Autoload/Autosave) then you can close all documents prior to saving your solution and thus receive a much faster start-up next time studio loads this solution.

This source available via GoogleCode and Subversion.
WorkBench available from http://dxcoreplugins.googlecode.com/svn/trunk/CR_WorkBench
Common code available from http://dxcoreplugins.googlecode.com/svn/trunk/Common

Tuesday, September 04, 2007

GoogleCode - DXCorePlugins

And so I have created a GoogleCode repository for an open source project called 'DXCorePlugins'.

I created 'DXCorePlugins' because I wanted a better way to manage my open source plugins for DXCore, CR and R!.

I irks me that I don't do as much work on said plugins as I would like to. I came to the conclusion that it was all the management that was becoming awkward.

i.e.
Creating versioned code...
... to make versioned assemblies...
... and building versioned zip files with both source code and binaries.
... updating web pages to reference said zip files and explain the purpose of each.

... trying to keep track of 'issues', 'bugs' and 'feature requests'

It's all management which distracts from the fun part.... making a cool plugin which does something to help people in their daily coding lives.

So I decided that I had to move the source code off my machine and into a repository of some kind. We use CVS at work but are thinking of moving to SubVersion. so ideally this would be a good chance to get to know said source control software on something less mission critical.

So I needed hosting of an open source project which ideally allowed SubVersion access to the repository of code.

2 obvious candidates: SourceForge and GoogleCode. This does not make a definitive set but this is a hobby project after all. I didn't want the research to take over my life.

It should be noted that I did consider Codeplex but decided against it because of what appeared to be a bias toward MS SCC API. To me MS SCC API shouts SourceSafe and I've been stung there before. Now I know that this is an unfair judgement, but ours is a small company and we cannot afford to spend too much time on micro-management so the fewer pieces involved, the better. I simply saw Subversion as a natural evolution of CVS and therefore when I saw that I would need to introduce additional pieces( some kind of SSC - Subversion bridge) I basically ruled out Codeplex then and there.

Now... to say that I was then left with SourceForge and GoogleCode is also something of an unfair statement. A more accurate statement would have been..."I was left with GoogleCode and, if I really had to, SourceForge".

You see, SourceForge has, for me, been the slowest of experiences. Accessing a SourceForge has always been like returning to the days of dial-up connections. It makes me wonder if this isn't the method they use to connect their servers to the internet. Now in fairness, I have been led to believe that this is not the case for everyone. many people apparently find SourceForge a very reasonable resource. however I am apparently not in that position. So from day one, If I could run without SourceForge, I was going to...

And therein lies my one regret. If not for this one issue I would simply have added my code to the CRPlugin project on SourceForge. I would recommend that these projects definitely be checked out.

And so unless GoogleCode was to provide and major stumbling blocks, I was going to use it.

So how does one create a project on GoogleCode?

Well it turns out it's really easy. Just show up at http://code.google.com/hosting/ and declare the Name and Licence of your project. That's essentially all there is to it. True you'll need an account with google, but who doesn't have a GMail account these days anyway.

The hard part was choosing a Licence for the project.

Now originally I wanted to specify do anything you like with the code except sell it (I wanted to encourage giving back to the community) but I realised I was spending way too much time considering the licence when... In truth, I didn't really care what people did with the code as long as they don't blame me for something it might do by mistake.

I stared at the list and their definitions for ages before I finally gave in and asked for help.

Trevor Westerdahl rescued me and pointed me in the direction of the MIT licence. Indicating "An MIT license is about as "open" as a license gets. It essentially protects the writer form any harm...as in there are no warranties of any kind, but allows for selling, copying, redistributing, etc."

It sounded good to me, and so there you have it. http://dxcoreplugins.googlecode.com/ is up and running with it's first project 'CR_WorkBench'.

Friday, August 10, 2007

Quick templates Example: Contact XML

A simple example of using "Quick Templates" with a simple piece of XML.
This is a very quick post to show an example of using "Quick Templates" to aid you
in the creation of a repetitive piece of XML
Imagine you have the following XML.
-------------------------------------------------------------
<Contact fname="Rory" lname="Becker"/>
-------------------------------------------------------------
You would like to have many more of these.
What to do?

- Highlight the XML to duplicate.
- Trigger my plugin. (I suggest attaching the "Create Quick Template" action to the "Alt-Q")
- Enter a few keys to trigger your template (In this case perhaps "con")
- Add some choice (crlf separated) keywords to the "Field list". (I think Rory and Becker would work well here. )
- Optionally: Setup a suitable context for you new template.
- Click Ok

Now whenever you activate the template by typing con and hitting space, you will find that the XML is repeated back
to you but that Coderush has wrapped my name (in this case) using it's nice glowing field markers. and you can
effectively type the following
-------------------------------------------------------------
con Mark Miller<enter>
con Carl Franklin<enter>
con Dustin Campbell<enter>
con Richard Campbell<enter>
-------------------------------------------------------------
...and create the following XML...
-------------------------------------------------------------
<Contact fname="Mark" lname="Miller" />
<Contact fname="Carl" lname="Franklin" />
<Contact fname="Dustin" lname="Campbell" />
<Contact fname="Richard" lname="Campbell" />
-------------------------------------------------------------

I'm sure there are many other uses for this.
Feel free to suggest some.

Thursday, August 09, 2007

QuickTemplates v0.5

Here's a sneak peek at my new QuickTemplates plugin.
QuickTemplates is a DXCore plugin which provides a new action to complement CodeRush Templates.

Available here(Updated to 0.51), it provides a quick method to create a template from text selected in the editor.

Setup:
1. Place QuickTemplates.Dll (Extract from obj folder or compile your own from the source) to your plugins folder and start VS.
2. Assign a key to the "Create Quick Template" action. I use "Alt-Q"

Usage:
1. Select some text
2. Activate the action (Alt-Q)
3. Assign a Name to the template.
4. Enter some words/phrases (CRLF separated) in the box labelled "Fields".
5. Configure any context you require.
6. Click 'Ok'

You will now have created a template complete with fields in place of appropriate phrases.

Here are some screenshots:



Friday, July 27, 2007

VS2008 Beta2. Installed and working :)

Well the download took it's sweet time, but as I say... It;s working.
Yup VS2008 Beta2 Pro is installed and ready to cook.

Note: I have also installed the very latest builds of Coderush and RefactorPro and both are working fine. I will say that I am in fact working with a "Daily Build" of each (version 2.2.4 - dated 27th July 2007) so your mileage may vary.

Sub note: If you're a subscriber to either then you to can request a "Daily Build" from the support team. Although these may not be "stable" builds. :)

Anyway back to VS2008. As I said it installed very nicely and appears to function very nicely. Worth saying that, whilst it is a little slow in places, the general experience is not bad at all.

So far I have only had time to check out 'XML-Literals' and hunt around for the Multi-Targeting (hard to find it but it's on the "Compile" tab of the project properties and is triggered by the "Advance Compile Options" button.

If there's anyone out there who is on or knows someone on the VB.net team, can you ask them to either beat the C# team into submission or alternatively cave themselves so that we can have a little more consistency in the placement of such "Cross language" features.

Having said that much Kudos to said VB.net team. I love XML Literals. Now I just have to find out how to extract data from them as simply as declaring them.

I still haven't made up my mind (Yeah as if I could have done that about anything in so short a space of time.) about whether or not I like the hyper enthusiastic intellisense.
On the one hand it does help with things like XML-Literal syntax but then it is very hard to take when it blocks Coderush's 'ms' template. (and many more I suspect.)

Ok that's it for now. I'll let y'all know how I get on as and when I discover new and cool stuff.

Thursday, July 26, 2007

VS2008 Beta2

VS2008 Beta 2 is available. that's right it's here and this time I'm gonna install it.
Yup the Beta 1 only made it into a VM on my home box. This time I'm gonna just install it. Yeah I know I'm risking it all, but I heard good things about Beta 1 and I assume(yeah I know) that things have only got better. So here I go....

Thursday, May 10, 2007

Add Namespace

I just knocked up a new RefactorPro plugin which uses the refactoring menu to Add a Namespace around a Class, Module or other Namespace
Find it in this thread of the new Developer Express Forums.

Monday, April 23, 2007

I just snapped up Winsnap

In an effort to encourage myself to create some more useful Blog posts and Wiki entries, I have purchased a copy of WinSnap by Alexander Avdonin.I feel this has to be one of the best capture tools I have ever used. It's simple, effective, "does exactly what it says on the tin".

It captures... Screens, Applications, Windows, Regions, Objects and Menus.

It Rotates, Scales, Adds Watermarks and Inverts.

It even adds curved edges to your window shots and it even has a portable edition.

The only thing it doesn't seem able to do is take shots of itself.

It has so many super powers that it must surely be in league with the devil.

Actually some would say it is.... it may not slice or dice but that's because it can hand your little screenshot off to Microsoft's Paint.

I think you'll agree that this is one capable little program.

Oh yeah and it's < 500Kb to download. and the registered edition is only $19.95