Answered by:
Custom handling of .js files in custom projects

Question
-
Hey there,
I'm writing a VS package for VS 2010 and above.
Here's a simple project which reproduces my issue and what I try to achieve:
Basically, I create:
- A custom project type (myproj) using the MPF
- A classifier for a custom language MyScript
- A language info for the language MyScript
The tricky thing is that I need for my script language to use the .js extension.
So I can neither use:
[ProvideLanguageExtension(typeof(MyScriptLanguageInfo), ".js")]
nor
[Export] [FileExtension(".js")] [ContentType(MyScriptContentType)] internal static FileExtensionToContentTypeDefinition MyScriptFileExtensionDefinition;
because either of those will override and break the default handling of .js files outside of .myproj projects.
To sum up, I want the MyScript classifier to be used for .js files inside .myproj project files, and that it doesn't interfere with the normal JavaScript handling outside of .myproj projects.
I have the feeling that I'm not that far away in the repro and that it has something to do with my editor factory. Currently it won't use my classifier inside my project, despite me trying to use my custom EditorFactory on my custom project.
I'd love if someone could have a look at the repro (it contains the MyScript solution and a sample myproj, I made it super easy to try) and provide some guidance.
Thanks!
- Edited by Jb Evain Tuesday, September 10, 2013 4:44 PM details
Monday, September 9, 2013 8:35 PM
Answers
-
Jb,
I apologize for the long delay in getting a response to you. Although this has been an interesting question, it has also been a tricky one to answer. I had to go to people in the product group directly to get their ideas. I order to avoid some loss in translation, I'm going to copy and paste some of the ideas I collected. Please let me know which, if any, of these ideas you find most useful or promising, and if you need more clarity about them:
From "Jared":
"Why not just always create the classifier? When the project system detects a .js file being open that is a part of its system it can set a flag, add something to the property bag, etc. Until that happens the custom classifier is a complete no-op (returns nothing, raises no events). Once that flag is set though it begins to behave normally. "
also from Jared:
"Another option is to just have a shared MEF component that is imported by both the project system and the classifiers.
interface INeedABetterName { event EventHandler Changed;
bool IsFileInProject(ITextBuffer textBuffer);
bool SetFileInProject(ITextBuffer textBuffer);
}This service could be imported by both the classifier implementation and the project system. The classifier uses the Changed event and IsFileInProject to determine if it should be providing tags. The project system just calls SetFileInProject for every file opened that is a part of it's project. This should be enough information to make this scenario work"
From "Dino":
"You'll probably want to set the flag in IVsProject.OpenItem. Depending on when the IClassifierProvider is called to get the classifier the "flag" might have to end up being a set of filenames where your classifier is used. Or maybe the provider will be called before OpenItem returns in which case it could just be a static or a bool set on your IClassifierProvider which you get back to via MEF.
Another possibility (and I think a little cleaner) is that you simply implement your own editor factory and have IVsProject.OpenItem open with that editor type. A slightly more complicated version of this exists in PTVS for Django support. There we want to open .html files with the Django editor factory and set them up with a projection buffer where we have the underlying HTML classifier doing most of the work with certain regions classified as another type. My guess is that you could cut that code down and just create a normal editor buffer with your content type rather than setting up the projection buffer. It might be simple as getting the text buffer after it's fully initialized and changing its content type.
You can find the PTVS source code for this at https://pytools.codeplex.com/SourceControl/latest w/ the relevant files being DjangoProject.cs where IVsProject.OpenItem is implemented and DjangoEditorFactory where the new projection buffer is created."
Scot
Developer Support Engineer
- Edited by Scot Br - MSFTMicrosoft employee Wednesday, September 25, 2013 7:30 PM bad quote characters
- Proposed as answer by Jane Wang - MSFT Thursday, October 3, 2013 1:33 AM
- Marked as answer by Jane Wang - MSFT Tuesday, October 8, 2013 6:25 AM
Wednesday, September 25, 2013 7:29 PM
All replies
-
Hi,
I am trying to reproduce this issue at present,and will give another response later.
Thanks for your patience.
Regards,
Jane.
<THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
Thanks
MSDN Community Support
Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.Tuesday, September 10, 2013 11:09 AM -
Hey Jane,
Thank you for having a look at my issue.
Don't hesitate to get back to me if you have any question.
Best regards,
Jb
Thursday, September 12, 2013 8:11 AM -
Hi Jb,
I feel sorry for that I am not able to solve this issue.
I have delivered this case to the professional team for better response.
It might take some time,while I think you could also get the appropriate suggestions.
Best Regards,
Jane.
<THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
Thanks
MSDN Community Support
Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.Thursday, September 12, 2013 11:17 AM -
Hi Jane,
Thanks for sending this internally.
Any news?
Monday, September 23, 2013 11:45 AM -
Hi,
I am waiting for the good news with you.
Have a nice day.
Jane.
<THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
Thanks
MSDN Community Support
Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.Monday, September 23, 2013 12:03 PM -
Jb,
I apologize for the long delay in getting a response to you. Although this has been an interesting question, it has also been a tricky one to answer. I had to go to people in the product group directly to get their ideas. I order to avoid some loss in translation, I'm going to copy and paste some of the ideas I collected. Please let me know which, if any, of these ideas you find most useful or promising, and if you need more clarity about them:
From "Jared":
"Why not just always create the classifier? When the project system detects a .js file being open that is a part of its system it can set a flag, add something to the property bag, etc. Until that happens the custom classifier is a complete no-op (returns nothing, raises no events). Once that flag is set though it begins to behave normally. "
also from Jared:
"Another option is to just have a shared MEF component that is imported by both the project system and the classifiers.
interface INeedABetterName { event EventHandler Changed;
bool IsFileInProject(ITextBuffer textBuffer);
bool SetFileInProject(ITextBuffer textBuffer);
}This service could be imported by both the classifier implementation and the project system. The classifier uses the Changed event and IsFileInProject to determine if it should be providing tags. The project system just calls SetFileInProject for every file opened that is a part of it's project. This should be enough information to make this scenario work"
From "Dino":
"You'll probably want to set the flag in IVsProject.OpenItem. Depending on when the IClassifierProvider is called to get the classifier the "flag" might have to end up being a set of filenames where your classifier is used. Or maybe the provider will be called before OpenItem returns in which case it could just be a static or a bool set on your IClassifierProvider which you get back to via MEF.
Another possibility (and I think a little cleaner) is that you simply implement your own editor factory and have IVsProject.OpenItem open with that editor type. A slightly more complicated version of this exists in PTVS for Django support. There we want to open .html files with the Django editor factory and set them up with a projection buffer where we have the underlying HTML classifier doing most of the work with certain regions classified as another type. My guess is that you could cut that code down and just create a normal editor buffer with your content type rather than setting up the projection buffer. It might be simple as getting the text buffer after it's fully initialized and changing its content type.
You can find the PTVS source code for this at https://pytools.codeplex.com/SourceControl/latest w/ the relevant files being DjangoProject.cs where IVsProject.OpenItem is implemented and DjangoEditorFactory where the new projection buffer is created."
Scot
Developer Support Engineer
- Edited by Scot Br - MSFTMicrosoft employee Wednesday, September 25, 2013 7:30 PM bad quote characters
- Proposed as answer by Jane Wang - MSFT Thursday, October 3, 2013 1:33 AM
- Marked as answer by Jane Wang - MSFT Tuesday, October 8, 2013 6:25 AM
Wednesday, September 25, 2013 7:29 PM -
Hey Scot,
Thanks a ton! We'll investigate the suggestions and get back to this thread if we have more questions.
Please thanks everyone involved for us!
Jb
Friday, September 27, 2013 1:12 PM -
Jb,
I look forward to news of your progress. Please let me know if you find these tips helpful enough, or if more is needed.
Scot
Developer Support Engineer
- Edited by Scot Br - MSFTMicrosoft employee Saturday, September 28, 2013 12:28 AM
Saturday, September 28, 2013 12:27 AM -
Jb,
I've been monitoring this thread, in case you had follow up questions. How do things look so far? Do you expect you may need more assistance?
Scot
Developer Support Engineer
Wednesday, October 2, 2013 5:17 PM -
Jb,
I would mark this reply as answer at present.
If you think it doesn't help, please feel free to unmark it.
Best Regards,
Jane.
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.Tuesday, October 8, 2013 6:27 AM -
Scot,
We basically ended up implementing something along the lines of what Dino suggested.
We're basically changing the content type of the TextBuffer directly when the specific project is opening the .js file, we just had to go through some hoops to get the textbuffer from the window frame.
Thanks a ton to everyone involved!
Thursday, October 10, 2013 4:31 PM -
A small reply to myself in case someone else feels the need to do the same.
Changing the content type was not enough for a few reasons: the JavaScript service was still initialized by the editor factory, and if you were to close VS with the file open, it would not reopen with our custom content type.
We created a custom editor factory that we're passing whenever we need to open a file, be it from the solution explorer, or from the task list, etc.
Thursday, November 14, 2013 9:29 AM