SQL Intellisense

Hello

I try to build a plug in for Resharper 2.x which will do SQL Intellisense.

Can anybody point me in the right direction how to do Intellisense with the
Open API. I need a starting point. I can't find anything about Intellisense
in the samples, so I do not know where to start.

Second I need to know, if the actual document is a SQL-document and third I
need an event that is fired when the '.' is pressed on the keyboard.

Thanks in advance
Michael




5 comments
Comment actions Permalink

would like to do the same... any advances you would like to share?


Michael Reukauff wrote:

Hello

I try to build a plug in for Resharper 2.x which will do SQL Intellisense.

Can anybody point me in the right direction how to do Intellisense with the
Open API. I need a starting point. I can't find anything about Intellisense
in the samples, so I do not know where to start.

Second I need to know, if the actual document is a SQL-document and third I
need an event that is fired when the '.' is pressed on the keyboard.

Thanks in advance
Michael



0
Comment actions Permalink

Yes, but I haven't started yet. I am still trying to find some infos on that
item. I am waiting of a response from the resharper team to my questions.

Michael

"luxspes" <me@privacy.net> wrote in message
news:dmvng0$fvv$2@is.intellij.net...

would like to do the same... any advances you would like to share?

>
>

Michael Reukauff wrote:

>> Hello
>>
>> I try to build a plug in for Resharper 2.x which will do SQL
>> Intellisense.
>>
>> Can anybody point me in the right direction how to do Intellisense with
>> the Open API. I need a starting point. I can't find anything about
>> Intellisense in the samples, so I do not know where to start.
>>
>> Second I need to know, if the actual document is a SQL-document and
>> third I need an event that is fired when the '.' is pressed on the
>> keyboard.
>>
>> Thanks in advance
>> Michael
>>
>>
>>

0
Comment actions Permalink

Hello Michael,

To have intellisense in SQL files you should follow these instructions:

1. First of all you need to build PSI (Program Structure Interface) for your
SQL files (that is: Abstract Syntax Tree and related services)
a) You need to implement the JetBrains.ReSharper.Psi.ISupportedByPSIChecker
interface (it's defined in JetBrains.ReSharper.Psi.dll). This interface has
a single method which tells the PsiManager whether it should build Psi for
the specified file or not. You should also mark your implementation class
with JetBrains.ReSharper.Psi.BuildPsiProviderAttribute (JetBrains.ReSharper.Psi.dll)
and pass ProgramConfigurations.VS_ADDIN (the ProgramConfigurations enum is
defined in JetBrains.ReSharper.Component namespace in JetBrains.ReSharper.Shell.dll)
Here's how the typical implementation should look like:


public class SQLSupport : ISupportedByPSIChecker
{
public bool Check(IProjectFile projectFile)
{
if(projectFile.Name.ToLower(CultureInfo.InvariantCulture).EndsWith(".sql"))
//Check whether this is an sql file
{
return true;
}

return false;
}
}


b) You need to define a language service for your SQL files:
You should create a class inheriting the JetBrains.ReSharper.Psi.LanguageService
class (JetBrains.ReSharper.Psi.dll) and implement it like this:



public class SQLLanguageService : LanguageService, IShellComponent
{
public static LanguageType SQL_LANGUAGE_TYPE = new LanguageType("SQL_LANGUAGE_TYPE",
"SQL script"); //It's a static variable which is used throughout the PSI
to identify the language type for your SQL script

public override IRawLexer CreateLexer(char[] buffer)
{
//Here you should return a lexer for your SQL files e.g. your implementation
of IRawLexer interface (it's located in JetBrains.ReSharper.Lexing namespace
in JetBrains.ReSharper.Psi.dll
}

public override ILexer CreateFilteringLexer(ILexer lexer)
{
return lexer;
}

public override CachingLexer CreateCachingLexer(char[] buffer)
{
return base.CreateCachingLexer(buffer);
}

public override IParser CreateParser(ILexer lexer, IProject project)
{
return new SQLParser(lexer); //Here you should return a parser for
SQL files which builds the Abstract Syntax Tree. The IParser interface is
defined in JetBrains.ReSharper.Psi namespace in JetBrains.ReSharper.Psi.dll.
More on parsing files follows
}

public override string[] EnumerateParserCapabilities()
{
return base.EnumerateParserCapabilities();
}

public override ITreeNode ParseUsingCapability(string text, string capability,
IProject project)
{
return base.ParseUsingCapability(text, capability, project);
}

public override LanguageType LanguageType
{
get { return SQL_LANGUAGE_TYPE; }
}

public override ISymbolCacheLanguageProvider SymbolCacheLanguageProvider
{
get {
//Here you should return your implementation of ISymbolCacheLanguageProvider
(it's located in JetBrains.ReSharper.Psi.Impl.Caches namespace in JetBrains.ReSharper.Psi.dll.
Or you can try returning null here.
}
}

public override ILanguageCacheProvider CacheProvider
{
get {
//You should return your implementation of ILanguageCacheProvider
here (it's located in JetBrains.ReSharper.Psi.ExtentionsAPI.Caches2 namespace
in JetBrains.ReSharper.Psi.dll) or you can try returning null
}
}

public void Init()
{
LanguageServiceManager.Instance.RegisterLanguageService(SQL_LANGUAGE_SERVICE,
this); //register your language service
LanguageServiceManager.Instance.BindExtension(".sql", this); //bind
a file extention to your language service
}

public void Dispose() {}

//Other properties and methods should have default implementation (that is:
they should return null or false)
}

c) Implementing IParser
You should develop a good type hierarchy for your syntax tree:

-The root node for the tree must always be a file (it should inherit FileElementBase
(JetBrains.ReSharper.Psi.ExtentionsAPI.Tree namespace in JetBrains.ReSharper.Psi.dll
and it should implement the IFileNode interface (JetBrains.ReSharper.Psi
namespace in JetBrains.ReSharper.Psi.dll))

-Each node of the tree must implement ITreeNode interface or ITokenNode depending
on what type of nodes it represents - a complex node with children or a leaf
node representing a single token. Actually you don't need to implement these
interfaces from scratch, because several base classes exist: you should use
JetBrains.ReSharper.Psi.ExtensionsAPI.Tree.CompositeElement (in JetBrains.ReSharper.Psi.dll)
for nodes, which can have children and JetBrains.ReSharper.Psi.ExtensionsAPI.Tree.LeafElement
(int JetBrains.ReSharper.Psi.dll) for leaf nodes, which represent single
tokens

-Note that after parsing a file the following should be true: if you call
GetText() method of the root node (file node) of your tree, the string it
returns must be identical to the original file's text.

2. Implementing code completion
a) To implement code completion for your files, you should add completion
rules, which will fill a list of completion items (the code completion list)
for the given context:

-You should implement the IRule interface (it's defined in JetBrains.ReSharper.CodeInsight.CodeCompletion
namespace in JetBrains.ReSharper.CodeInsight.dll) and mark your implementation
class with the RuleAttribute which is defined in the same place.

-The CanGenerate property of your Rule must always return "true".

-The IsApplicable method determines whether this rule is applicable in the
given context (see JetBrains.ReSharper.CodeInsight.CodeCompletion.CodeCompletionContext
in JetBrains.ReSharper.CodeInsight.dll for more information).

-The Apply method should fill the "result" list with completion items. Each
item in this list must implement the JetBrains.ReSharper.CodeInsight.Services.Lookup.ILookupItem
interface (it's defined in JetBrains.ReSharper.CodeInsight.Services.dll)
The typical implementation of ILookupItem interface should look like this:

public class SQLLookupItem : ILookupItem
{
private int _Index;
private string _ItemName;
private Image _Image = null;

public SQLLookupItem(string itemName)
{
_ItemName = itemName;

try
{
_Image = Image.FromStream(...)//Load your image here
}
catch (Exception e)
{
Logger.LogExceptionSilently(e);
}
}

/// /// Gets or sets item index. Used for fast sorting. /// public int Index { get { return _Index; } set { _Index = value; } } ///

/// Gets lookup item image /// public Image Image { get { return _Image; } } /// /// Gets lookup item display name /// public RichText DisplayName { get { return new RichText(_ItemName, new RichTextParameters(FontsManager.Instance.LookupFont)); } } /// /// Gets type display name /// public RichText DisplayTypeName { get { return null; } } /// /// Shrinks lookup item presentation /// public bool Shrink() { return false; } /// /// Restores unshrinked lookup item presentation /// public void CancelShrink() { } /// /// Gets lookup item type-in name /// public string TypeInName { get { return _ItemName; } } /// /// Completes the item at the specified range. /// public void Complete(ITextControl textControl, TextRange nameRange, LookupItemInsertType lookupItemInsertType, string suffix, ISolution solution) { try { CommandProcessor.Instance.BeginCommand("Complete SQL"); //Start a batch command textControl.Document.DeleteText(nameRange); //Delete part of the completed name textControl.Document.InsertText(nameRange.StartOffset, _ItemName); //Insert the full item name textControl.CaretModel.MoveTo(nameRange.StartOffset + _ItemName.Length); //Move the caret to the end of the name } finally { CommandProcessor.Instance.EndCommand(); //End the batch command } } /// /// Gets visual replace range /// ]]>
public TextRange GetVisualReplaceRange(ITextControl textControl, TextRange
nameRange)
{
return TextRange.InvalidRange;
}
}



Of course it's just a small guideline on how to support a third party language
with ReSharper's open API, so if you have any questions, we're ready to answer
them.

Andrey Serebryansky
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


0
Comment actions Permalink

Hi!
First, thanks a lot for all the previously posted info!
Now.. two questions:

The lexer has to be implemented "by hand" or we can use a tool like
ANTLR (http://www.antlr.org/)? If both ways are possible... do you
recommend a particular approach? or perhaps a particular "Lexer" generator?

The parser has to be implemented "by hand" or we can use a tool like
ANTLR? If both ways are possible... do you recommend a particular
approach? or perhaps a particular "Parser" generator?

0
Comment actions Permalink

Hello Luxspes,

it's completely up to you how you implement lexer & parser. You'll only need
to expose a set of PSI interfaces in your syntax tree.

As for recommendation, we ourselves use the csLex lexer generator combined
with a hand-made lexer optimizations aimed to improve its performance. For
parsers, we use a homegrown tool, but it's not publicly available. As with
lexers,
a part of C# parser is written manually. If I were you, I'd take a look at
open-source
SQL parsers - I'm sure they exist, may be even in C#. An important concern
with regard to a parser is that it needs to preserve the entire text structure
including
whitespaces. The simplest approach for doing this is having whitespaces attached
to the
syntax trees like regular grammar nodes - that's how we do for C#.

Regards,
Dmitry Shaporenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

Hi!
First, thanks a lot for all the previously posted info!
Now.. two questions:
The lexer has to be implemented "by hand" or we can use a tool like
ANTLR (http://www.antlr.org/)? If both ways are possible... do you
recommend a particular approach? or perhaps a particular "Lexer"
generator?

The parser has to be implemented "by hand" or we can use a tool like
ANTLR? If both ways are possible... do you recommend a particular
approach? or perhaps a particular "Parser" generator?



0

Please sign in to leave a comment.