[svn]
r6961: vs-plugin/trunk/Nemerle.VsIntegration/Project/NemerleFileNodeCodeDomProvider.cs
akhropov
svnadmin at nemerle.org
Sun Nov 19 21:12:35 CET 2006
Log:
fix designer crash bug + some improvements
Author: akhropov
Date: Sun Nov 19 21:12:22 2006
New Revision: 6961
Modified:
vs-plugin/trunk/Nemerle.VsIntegration/Project/NemerleFileNodeCodeDomProvider.cs
Modified: vs-plugin/trunk/Nemerle.VsIntegration/Project/NemerleFileNodeCodeDomProvider.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/Project/NemerleFileNodeCodeDomProvider.cs (original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/Project/NemerleFileNodeCodeDomProvider.cs Sun Nov 19 21:12:22 2006
@@ -3,6 +3,8 @@
using System.CodeDom;
using System.CodeDom.Compiler;
+using System.Diagnostics;
+
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
@@ -18,25 +20,54 @@
namespace Nemerle.VisualStudio.Project
{
- internal class NemerleFileNodeCodeDomProvider : CodeDomProvider,
- ICodeParser, ICodeGenerator
+ internal class NemerleCodeGeneratorProxy : NemerleCodeGenerator, ICodeGenerator
+ {
+ NemerleFileNodeCodeDomProvider _fileNodeProvider; // save this hook
+
+ public NemerleCodeGeneratorProxy(NemerleFileNodeCodeDomProvider fileNodeProvider)
+ {
+ _fileNodeProvider = fileNodeProvider;
+ }
+
+ public void GenerateCodeFromCompileUnit(CodeCompileUnit e, TextWriter w, CodeGeneratorOptions o)
+ {
+ _fileNodeProvider.GenerateCodeFromCompileUnit(e,w,o);
+ }
+ }
+
+ internal class NemerleFileNodeCodeDomProvider : CodeDomProvider, ICodeParser
+ // ICodeGenerator
{
FileNode _fileNode;
- NemerleCodeProvider _codeProvider;
+ //NemerleCodeProvider _codeProvider;
+ NCU.CodeDomParser _codeDomParser;
+ //NemerleCodeGenerator _codeGen;
+ ICodeGenerator _codeGen;
+ NemerleCodeGeneratorProxy _codeGenProxy;
// AKhropov: In fact these 2 constructors only to restrict possible file nodes,
// could be simply NemerleFileCodeDomProvider(FileNode fileNode)
+ private void Init()
+ {
+ _codeDomParser = new NCU.CodeDomParser();
+ _codeGen = new NemerleCodeGenerator();
+ _codeGenProxy = new NemerleCodeGeneratorProxy(this);
+ }
+
internal NemerleFileNodeCodeDomProvider(NemerleFileNode fileNode)
{
_fileNode = fileNode;
+ Init();
}
internal NemerleFileNodeCodeDomProvider(NemerleDependentFileNode fileNode)
{
_fileNode = fileNode;
+ Init();
}
+ /*
internal NemerleCodeProvider CodeProvider
{
get
@@ -46,6 +77,7 @@
return _codeProvider;
}
}
+ */
#region helper functions
@@ -74,7 +106,7 @@
}
// AKhropov : I had to copy it from FileNode implementation because it was protected there
- void UpdateGeneratedCodeFile(byte[] data, int size, string filePath)
+ void UpdateGeneratedCodeFile(string data, string filePath)
{
IVsRunningDocumentTable rdt = _fileNode.ProjectMgr.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
@@ -85,88 +117,18 @@
}
IVsHierarchy hier;
- uint cookie;
- uint itemid;
+ uint itemid, cookie;
IntPtr docData = IntPtr.Zero;
- ErrorHandler.ThrowOnFailure(rdt.FindAndLockDocument((uint)(_VSRDTFLAGS.RDT_NoLock), filePath, out hier, out itemid, out docData, out cookie));
+ //Getting a read lock on the document. Must be released later.
+ ErrorHandler.ThrowOnFailure(rdt.FindAndLockDocument((uint)(_VSRDTFLAGS.RDT_ReadLock), filePath, out hier, out itemid, out docData, out cookie));
if (docData != IntPtr.Zero)
{
+ IVsPersistDocData persistDocData = Marshal.GetObjectForIUnknown(docData) as IVsPersistDocData;
Marshal.Release(docData);
- IVsTextStream srpStream;
- string inputFileContents = GetBufferContents(_fileNode, filePath, out srpStream);
- if (srpStream != null)
- {
- int oldLen = 0;
- int hr = srpStream.GetSize(out oldLen);
- if (ErrorHandler.Succeeded(hr))
- {
- IntPtr dest = IntPtr.Zero;
- try
- {
- dest = Marshal.AllocCoTaskMem(data.Length);
- Marshal.Copy(data, 0, dest, data.Length);
- ErrorHandler.ThrowOnFailure(srpStream.ReplaceStream(0, oldLen, dest, size / 2));
- }
- finally
- {
- if (dest != IntPtr.Zero)
- {
- Marshal.Release(dest);
- }
- }
- }
- }
- }
- else
- {
- using (FileStream generatedFileStream = File.Open(filePath, FileMode.OpenOrCreate))
- {
- generatedFileStream.Write(data, 0, size);
- }
-
- EnvDTE.ProjectItem projectItem = _fileNode.GetAutomationObject() as EnvDTE.ProjectItem;
- if (projectItem != null && (_fileNode.ProjectMgr.FindChild(_fileNode.FileName) == null))
- {
- projectItem.ProjectItems.AddFromFile(filePath);
- }
- }
- }
-
- /// <summary>
- /// Returns the buffer contents for the current node.
- /// </summary>
- /// <returns>Buffer contents</returns>
- private string GetBufferContents(FileNode fileNode, string fileName, out IVsTextStream srpStream)
- {
- Guid CLSID_VsTextBuffer = new Guid("{8E7B96A8-E33D-11d0-A6D5-00C04FB67F6A}");
- string bufferContents = "";
- srpStream = null;
- IVsRunningDocumentTable rdt = fileNode.ProjectMgr.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
- if (rdt != null)
- {
- IVsHierarchy hier;
- IVsPersistDocData persistDocData;
- uint itemid, cookie;
- bool docInRdt = true;
- IntPtr docData;
- //Getting a read lock on the document. Must be released later.
- int hr = rdt.FindAndLockDocument((uint)_VSRDTFLAGS.RDT_ReadLock, fileName, out hier, out itemid, out docData, out cookie);
- if (ErrorHandler.Failed(hr) || docData == IntPtr.Zero)
+ try
{
- Guid iid = VSConstants.IID_IUnknown;
- cookie = 0;
- docInRdt = false;
- ILocalRegistry localReg = fileNode.ProjectMgr.GetService(typeof(SLocalRegistry)) as ILocalRegistry;
- ErrorHandler.ThrowOnFailure(localReg.CreateInstance(CLSID_VsTextBuffer, null, ref iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, out docData));
- }
-
- persistDocData = Marshal.GetObjectForIUnknown(docData) as IVsPersistDocData;
- //Release
- if (docData != IntPtr.Zero)
- Marshal.Release(docData);
-
- //Try to get the Text lines
+ // Try to get the Text lines
IVsTextLines srpTextLines = persistDocData as IVsTextLines;
if (srpTextLines == null)
{
@@ -174,59 +136,58 @@
IVsTextBufferProvider srpTextBufferProvider = persistDocData as IVsTextBufferProvider;
if (srpTextBufferProvider != null)
{
- hr = srpTextBufferProvider.GetTextBuffer(out srpTextLines);
+ ErrorHandler.ThrowOnFailure(srpTextBufferProvider.GetTextBuffer(out srpTextLines));
}
+ // TODO : handle null case
}
- if (ErrorHandler.Succeeded(hr))
- {
- srpStream = srpTextLines as IVsTextStream;
- if (srpStream != null)
- {
- // QI for IVsBatchUpdate and call FlushPendingUpdates if they support it
- IVsBatchUpdate srpBatchUpdate = srpStream as IVsBatchUpdate;
- if (srpBatchUpdate != null)
- srpBatchUpdate.FlushPendingUpdates(0);
-
- int lBufferSize = 0;
- hr = srpStream.GetSize(out lBufferSize);
+ int endLine, endIndex;
+ srpTextLines.GetLastLineIndex(out endLine, out endIndex);
- if (ErrorHandler.Succeeded(hr))
+ // Lock the buffer before changing its content.
+ ErrorHandler.ThrowOnFailure(srpTextLines.LockBuffer());
+ try
{
- IntPtr dest = IntPtr.Zero;
+ GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
- // Note that GetStream returns Unicode to us so we don't need to do any conversions
- dest = Marshal.AllocCoTaskMem((lBufferSize + 1) * 2);
- ErrorHandler.ThrowOnFailure(srpStream.GetStream(0, lBufferSize, dest));
- //Get the contents
- bufferContents = Marshal.PtrToStringUni(dest);
+ TextSpan[] span = new TextSpan[1];
+ ErrorHandler.ThrowOnFailure(srpTextLines.ReplaceLines(0, 0, endLine, endIndex, handle.AddrOfPinnedObject(), data.Length, span));
}
finally
{
- if (dest != IntPtr.Zero)
- Marshal.FreeCoTaskMem(dest);
+ // Free the memory.
+ handle.Free();
}
}
+ finally
+ {
+ // Make sure that the buffer is unlocked also in case of exception.
+ srpTextLines.UnlockBuffer();
}
-
}
- // Unlock the document in the RDT if necessary
- if (docInRdt && rdt != null)
+ finally
{
ErrorHandler.ThrowOnFailure(rdt.UnlockDocument((uint)(_VSRDTFLAGS.RDT_ReadLock | _VSRDTFLAGS.RDT_Unlock_NoSave), cookie));
}
+ }
+ else
+ {
+ using (StreamWriter sw = new StreamWriter(filePath,false))
+ {
+ sw.Write( data );
+ }
- if (ErrorHandler.Failed(hr))
+ EnvDTE.ProjectItem projectItem = _fileNode.GetAutomationObject() as EnvDTE.ProjectItem;
+ if (projectItem != null && (_fileNode.ProjectMgr.FindChild(_fileNode.FileName) == null))
{
- // If this failed then it's probably not a text file. In that case,
- // we just read the file as a binary
- bufferContents = File.ReadAllText(fileName);
+ projectItem.ProjectItems.AddFromFile(filePath);
}
}
- return bufferContents;
}
+
+
#endregion
#region Parser implementation
@@ -234,13 +195,10 @@
public override CodeCompileUnit Parse(TextReader codeStream)
{
// AKhropov - in fact codeStream is ignored for now
-
- NCU.CodeDomParser parser = new NCU.CodeDomParser();
-
string filePath = PathOfFileToParse();
ProjectInfo projectInfo = ProjectInfo.FindProject(filePath);
- return parser.CreateCodeCompileUnit( projectInfo.Engine.Project, filePath );
+ return _codeDomParser.CreateCodeCompileUnit(projectInfo.Engine.Project, filePath);
}
#endregion
@@ -249,25 +207,14 @@
public override void GenerateCodeFromCompileUnit(CodeCompileUnit e, TextWriter w, CodeGeneratorOptions o)
{
- using (MemoryStream memBuffer = new MemoryStream())
- {
- using (StreamWriter sw = new StreamWriter(memBuffer))
+ using (StringWriter sw = new StringWriter())
{
- _codeProvider.GenerateCodeFromCompileUnit(e, sw, o);
- }
+ _codeGen.GenerateCodeFromCompileUnit(e, sw, o);
- // TODO: long/int inconsistency
- UpdateGeneratedCodeFile(memBuffer.GetBuffer(), (int)memBuffer.Length, PathOfFileToParse());
+ UpdateGeneratedCodeFile(sw.ToString(), PathOfFileToParse());
}
}
- // AKhropov : Just to fill ICodeGenerator
- public void ValidateIdentifier(string value)
- {
- if (!CodeProvider.IsValidIdentifier(value))
- throw new ArgumentException();
- }
-
#endregion
#region Provided (obsolete) interfaces
@@ -281,20 +228,21 @@
[Obsolete("Callers should not use the ICodeGenerator interface.")]
public override ICodeGenerator CreateGenerator()
{
- return this;
+ return _codeGenProxy;
}
[Obsolete("Callers should not use the ICodeCompiler interface.")]
public override ICodeCompiler CreateCompiler()
{
- /* TODO - maybe return CodeProvider.CreateCompiler();
- but now doesn't make mush sense
+ /* TODO - maybe return base.CreateCompiler();
+ but now doesn't make much sense
*/
throw new NotImplementedException();
//return null;
}
+
#endregion
#region Overridden properties
More information about the svn
mailing list