Friday, May 23, 2008

Snippet Definition Commentary

Snippets are probably the most powerful code generation tool available in Visual Studio. The power result from simplicity blended with extensibility.

To better show this combination of ease and flexibility I am going to dissect the 'class' snippet.

It is stored as XML so it has the xml directive to start and the top element is 'CodeSnippets' which has one or more 'CodeSnippet' elements so the boilerplate for all snippets looks like:


<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">

</CodeSnippet>
</CodeSnippets>




A 'CodeSnippet' element has two child elements 'Header' and 'Snippet'
Header contains information about how the snippet should be used.
Snippet defines how code generation.



<CodeSnippet Format="1.0.0">
<Header>

</Header>
<Snippet>

</Snippet>
</CodeSnippet>




The 'Header' element has child elements of 'Title', 'Shortcut', 'Description', 'Author' and 'SnippetTypes'.
Visual Studio uses the 'Shortcut' element's value to autosuggest the snippet. In this case the value of 'class' which is also a keyword helps suggest this snippet at the right time.
Since there is no restriction on uniqueness of snippet names, the IDE will show that there are multiple snippets for the same snippet shortcut.
The 'Title' and 'Description' will allow users to select the appropriate one.
Another key element with snippets is the 'SnippetTypes' which can have one or more 'SnippetType' child elements.
In this case it indicates that the class snippet can be used to both expand and surround code. The surrounds value indicates that if some text is selected and the snippet is invoked the selected text will be used.


<Header>
<Title>class</Title>
<Shortcut>class</Shortcut>
<Description>Code snippet for class</Description>
<Author>Microsoft Corporation</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>




The 'Snippet' element is where all the code generation work is defined.
In order for the snippet to something more powerful than copy and paste we need a way to declare some placeholders.
That is what the 'Declarations' element with 'Literal' child elements define. The 'ID' child of 'Literal' in this case is 'name' in the 'Code' element this is important.
The 'ToolTip' provides context sensitive information when using the element. The 'Default' element give the 'Literal' a value at the start.

The 'Code' child element of 'Snippet' has the body of the code to be created. When this is done the user selected values of the 'Literals' will be substituted.
So the 'Literal' with 'ID' of 'name' is seen here as '$name$'. There are a few built in and implied literals as well.
When the snippet is used in 'SurroundsWith' mode the selected text provides the value for the implied '$selected$'


<Snippet>
<Declarations>
<Literal>
<ID>name</ID>
<ToolTip>Class name</ToolTip>
<Default>MyClass</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[class $name$
{
$selected$$end$
}]]>
</Code>
</Snippet>





Now having all the details and a working example
all one needs to create a snippet is a chunk of code
that is constantly being used.
Simply put it in the 'Code' element.
Then repeatedly extract literals from the code.
Define the literals in the header and you are done.

No comments: