Visual Studio Development Bookmark and Share   
 index > Visual Studio Extensibility > Isolated shell: LanguageService/BabelLanguageService - Source object problems
 

Isolated shell: LanguageService/BabelLanguageService - Source object problems

Hello again

After relative long time without major problems I've found one that I cannot deal with.
Here is overview:

I've created visual studio extension for language used in my company. It's based mostly on IronPython, and it almost works :)
Ok, it works. But there is one small problem: I'd like to include feature that makes changes inside text file when user changes its name in solution explorer. For example: if user changes name of the file from "File1" to "File2", first method's name inside this file is being changed from File1 to File2. Please don't ask me why to do this...

Anyway I've localised method "ParseSource" inside LanguageService package. Inside it there is object of type Source, called "source".
It has method called SetText that, in theory (http://msdn.microsoft.com/zh-cn/library/bb135763.aspx) can change text. Unfortunately there is small problem when I try to do this. There is COM exception thrown:

So I have a question: is this only my problem? I mean: only I experience this? If so, is there a other way to achieve goal that I described above? If I'd find the way to set text, how to know when name of the file is changed? Is there any event or so?

Thank you in advance
Best regards
Paul
PaulTheMe  Monday, October 05, 2009 8:43 AM
Hi Paul,

I did a quick check of the rename feature as implemented by C#. When the user attempts to rename a file via the solution explorer, the underlying project hierarchy's implementation of IVsUIHierarchy::SetProperty is invoked to set the VSHPROPID_EditLabel. When this in called the underlying project system renames the file and then uses the underlying CodeElement2::RenameSymbol to refactor the base class name.

If your project type is based on the MPF_Proj sources, I suspect you could add the refactoring capability at the end of the internal RenameDocument method on the FileNode class. That would probably be a logical place to start.

Sincerely,
Ed Dore
Ed Dore  Monday, October 12, 2009 9:03 PM

Hi, Paul

For the exception, I would much appreciate you, if you could post your solution here. For your second question, the automation model has already provide you the event for the renaming of projectItem. For this you can reference this ProjectItemsEventsClass.ItemRenamed Event.
Thanks
Chao

Chao Kuo  Wednesday, October 07, 2009 3:12 AM
Good day

Thank You for reply Chao. There are two things that I'd like to add.

1) Exception thing: I think that I've posted not clearly, and You took my question as an answer :) In my work I found this error(?) with Source object, and I cannot deal with it. COM exception is thrown, when I try to use method source.SetText("example"); I don't know why and how to fix it.

2)Event thing: great! But unfortunately don't work in my project :(. Here is how I use this. In my ProjectPackage I define new object:

public EnvDTE.ProjectItemsEventsClass eClass = new EnvDTE.ProjectItemsEventsClass();

Inside constructor I add:
 MyProjectPackage(){
   eClass.ItemRenamed += new EnvDTE._dispProjectItemsEvents_ItemRenamedEventHandler(eClass_ItemRenamed);
}

And inside class I

 

 

 define new method:

public sealed
class MyProjectPackage: ProjectPackage{
   void eClass_ItemRenamed(EnvDTE.ProjectItem ProjectItem, string OldName){
      throw new NotImplementedException();
    }
}

It compiles and when I try to run it, communication box pops up - something that ProjectPackage failed to load. I cannot open my custom project then.
Please - give me a piece of advice: do I do it right? Maybe I shouldn't define these objects/methods in this way?

Thank You in advance

Paul
PaulTheMe  Wednesday, October 07, 2009 7:30 AM

Hi, Paul

To ProjectItemsEventsClass.ItemRenamed Event, you should get the DTE service first. Just like.

            DTE dte = GetService(typeof(SDTE)) as DTE;
            dte.Events.SolutionItemsEvents.ItemRenamed += new _dispProjectItemsEvents_ItemRenamedEventHandler(eClass_ItemRenamed);

If GetService is not available, you should try Package.GetGlobalService(SDTE) method.
For the Com Exception, I am not able to diagnose your issue, for I don't know what do you write in your code. would you mind provide more details code here?
Thanks
Chao

Chao Kuo  Wednesday, October 07, 2009 10:20 AM

Hello again

Just like You said: GetService() doesn't work, so I used:

public
EnvDTE.DTE dte = PMLProjectPackage.GetGlobalService(typeof(SDTE)) as EnvDTE.DTE;

and, inside constructor:

dte.Events.SolutionItemsEvents.ItemRenamed +=
new EnvDTE._dispProjectItemsEvents_ItemRenamedEventHandler(SolutionItemsEvents_ItemRenamed);

Appropriate method does nothing (for now). But, unfortunately - it doesn't work again. I don't see how's that. On start dte is set, the same as event. I can see that during debugging. But when project is loaded, and I try to change name of file inside it, nothing happens. I set breakpoint in the method ItemRenamed, and it is never touched.

I don't know how it works. For me, it should be ok now, but event isn't fired or I can't catch it. Maybe You know what's going on?

About COM Exception, I'd like to provide more necessary details, but I don't know what do You want to know. In my LanguageService there is class:

 

public abstract class BabelLanguageService : Microsoft.VisualStudio.Package.LanguageService{

     public override Microsoft.VisualStudio.Package.AuthoringScope ParseSource(ParseRequest req){
        Source source =      (Source)this.GetSource(req.FileName);
        (......REST OF THE CODE) }
}

When I try to invoke source.SetText("example"), or other overloading of this method, COM exception is thrown:
A null reference pointer was passed to the stub. (Exception from HRESULT: 0x800706F4)

I'd like to change text in this source for purposes of parsing and merging code. This metod would be perfect (I think that becouse description on MSDN claims that :) ), but I cannot use it.

Thank You again for help
Best regards
Paul

PaulTheMe  Wednesday, October 07, 2009 1:41 PM
Hi Paul,

The problem is that you are attempting to retrieve the DTE automation service before your package is properly sited. Additionally, it's entirely possible for your package to be sited before the DTE service is available. The following blog article details why this occurs and how to avoid it.

   Dr. eX: Why does GetService(typeof(EnvDTE.DTE)) return NULL?


However, I believe the automation event is probably not the proper way to go about doing this. When a file is renamed, the DocData object associated with the project item gets a call to IVsPersistDocData.RenameDocData call. I suspect there are some other hooks like IVsRunningDocTableEvents. I need to do a little digging to find the right way to do this. I'll try to look this up and post back on this thread.

Sincerely,
Ed Dore
Ed Dore  Friday, October 09, 2009 4:53 AM

Ed,

Thank You for your concern, I really approciate this, and I'm waiting with anxiety for Your next post. Additionally I'm reading blog You mentioned about :), there is so many things about VS that I feel dizzy...
Best regards,
Paul.

PaulTheMe  Friday, October 09, 2009 5:20 AM
Hi Paul,

I did a quick check of the rename feature as implemented by C#. When the user attempts to rename a file via the solution explorer, the underlying project hierarchy's implementation of IVsUIHierarchy::SetProperty is invoked to set the VSHPROPID_EditLabel. When this in called the underlying project system renames the file and then uses the underlying CodeElement2::RenameSymbol to refactor the base class name.

If your project type is based on the MPF_Proj sources, I suspect you could add the refactoring capability at the end of the internal RenameDocument method on the FileNode class. That would probably be a logical place to start.

Sincerely,
Ed Dore
Ed Dore  Monday, October 12, 2009 9:03 PM

Hi again

Thank you Ed for yor time. You helped me a lot - I solved the problem with FileNode class, just like you said :) I mean - problem with renaming event. Problem with Source object still exists...

Right now I know when user renames file. So I'd like to change text in this file in order to changes in file name.  Source object contains text from the file, so I'd like to change this text with method SetText(), but it returns exception, just like I explained above. BUT: maybe this is not a problem for me and there is other way to change text in renamed file?

I would create textreader/writer and change file outside VS Shell, but then annoying window with information about this pops up. This isn't proper way. So maybe something else? I have almost no experience in such projects, so forgive me if I ask about basics...

Best regards
Paul

PaulTheMe  Wednesday, October 14, 2009 7:14 AM

You can use google to search for other answers

Custom Search

More Threads

• Invisible custom hierarchy window
• Getting list of test from Test List Editor
• Locate project's app.config from designer code?
• Programmatically Adding WPF Comtrol to VS 2008 ToolBox
• HowTo -- how to incorporate a Project SubType into the New Project classification
• all source code of the document
• javascript at VSX 2008 - enhance Intellisense + coloring
• Creating our own wizard for visual studio?
• Visual Studio 2005 Extensions for general .NET 3.0 development?
• Launching an IWizard Wizard