Ejemplo n.º 1
0
        /// <summary>
        /// Runs the generator on the current project item.
        /// </summary>
        /// <param name="document"></param>
        /// <returns></returns>
        public virtual void RunGeneratorEx(string document, bool runEvenIfNotDirty)
        {
            // Go run the generator on that node, but only if the file is dirty
            // in the running document table.  Otherwise there is no need to rerun
            // the generator because if the original document is not dirty then
            // the generated output should be already up to date.

            // the original implementation is crappy.  This method is called zillions of times by the environment,
            // so the first thing we should do is to see if there's any generator defined for this node.  Why see if the file
            // is dirty if there's no generator even defined???

            uint itemid = VSConstants.VSITEMID_NIL;

            ThreadHelper.ThrowIfNotOnUIThread();
            IVsHierarchy hier = (IVsHierarchy)this.ProjectMgr;

            if (document != null && hier != null && ErrorHandler.Succeeded(hier.ParseCanonicalName((string)document, out itemid)))
            {
                FileNode node = (FileNode)this.ProjectMgr.NodeFromItemId(itemid);

                SingleFileGeneratorNodeProperties nodeproperties = node.NodeProperties as SingleFileGeneratorNodeProperties;

                // not every node is necessarily going to have a properties object derived from SFGNodeProperties
                if (nodeproperties != null && !string.IsNullOrEmpty(nodeproperties.CustomTool))
                {
                    try
                    {
                        this.InvokeGeneratorEx(node, document, runEvenIfNotDirty);
                    }
                    catch (Exception e)
                    {
                        if (System.Diagnostics.Debugger.IsAttached)
                        {
                            Debug.WriteLine(e.Message);
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Invokes the specified generator
        /// </summary>
        /// <param name="fileNode">The node on which to invoke the generator.</param>
        public /*protected internal, but public for FSharp.Project.dll*/ virtual void InvokeGenerator(FileNode fileNode)
        {
            if (fileNode == null)
            {
                throw new ArgumentNullException("node");
            }

            SingleFileGeneratorNodeProperties nodeproperties = fileNode.NodeProperties as SingleFileGeneratorNodeProperties;

            if (nodeproperties == null)
            {
                throw new InvalidOperationException();
            }

            string customToolProgID = nodeproperties.CustomTool;

            if (string.IsNullOrEmpty(customToolProgID))
            {
                return;
            }

            string customToolNamespace = nodeproperties.CustomToolNamespace;

            try
            {
                if (!this.runningGenerator)
                {
                    //Get the buffer contents for the current node
                    string moniker = fileNode.GetMkDocument();

                    this.runningGenerator = true;

                    //Get the generator
                    IVsSingleFileGenerator generator;
                    int generateDesignTimeSource;
                    int generateSharedDesignTimeSource;
                    int generateTempPE;
                    SingleFileGeneratorFactory factory = new SingleFileGeneratorFactory(this.projectMgr.ProjectGuid, this.projectMgr.Site);
                    ErrorHandler.ThrowOnFailure(factory.CreateGeneratorInstance(customToolProgID, out generateDesignTimeSource, out generateSharedDesignTimeSource, out generateTempPE, out generator));

                    //Check to see if the generator supports siting
                    IObjectWithSite objWithSite = generator as IObjectWithSite;
                    if (objWithSite != null)
                    {
                        objWithSite.SetSite(fileNode.OleServiceProvider);
                    }

                    //Determine the namespace
                    if (string.IsNullOrEmpty(customToolNamespace))
                    {
                        customToolNamespace = this.ComputeNamespace(moniker);
                    }

                    //Run the generator
                    IntPtr[] output = new IntPtr[1];
                    output[0] = IntPtr.Zero;
                    uint   outPutSize;
                    string extension;
                    ErrorHandler.ThrowOnFailure(generator.DefaultExtension(out extension));

                    //Find if any dependent node exists
                    string        dependentNodeName = Path.GetFileNameWithoutExtension(fileNode.FileName) + extension;
                    HierarchyNode dependentNode     = fileNode.FirstChild;
                    while (dependentNode != null)
                    {
                        if (string.Compare(dependentNode.ItemNode.GetMetadata(ProjectFileConstants.DependentUpon), fileNode.FileName, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            dependentNodeName = ((FileNode)dependentNode).FileName;
                            break;
                        }

                        dependentNode = dependentNode.NextSibling;
                    }

                    //If you found a dependent node.
                    if (dependentNode != null)
                    {
                        //Then check out the node and dependent node from SCC
                        if (!this.CanEditFile(dependentNode.GetMkDocument()))
                        {
                            throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED);
                        }
                    }
                    else //It is a new node to be added to the project
                    {
                        // Check out the project file if necessary.
                        if (!this.projectMgr.QueryEditProjectFile(false))
                        {
                            throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED);
                        }
                    }
                    IVsTextStream stream;
                    string        inputFileContents = this.GetBufferContents(moniker, out stream);

                    ErrorHandler.ThrowOnFailure(generator.Generate(moniker, inputFileContents, customToolNamespace, output, out outPutSize, this));
                    byte[] data = new byte[outPutSize];

                    if (output[0] != IntPtr.Zero)
                    {
                        Marshal.Copy(output[0], data, 0, (int)outPutSize);
                        Marshal.FreeCoTaskMem(output[0]);
                    }

                    //Todo - Create a file and add it to the Project
                    string fileToAdd = this.UpdateGeneratedCodeFile(fileNode, data, (int)outPutSize, dependentNodeName);
                }
            }
            finally
            {
                this.runningGenerator = false;
            }
        }
Ejemplo n.º 3
0
        protected internal virtual void InvokeGeneratorEx(FileNode fileNode, String document, bool runEvenIfNotDirty)
        {
            base.InvokeGenerator(fileNode);
            Utilities.ArgumentNotNull("fileNode", fileNode);

            SingleFileGeneratorNodeProperties nodeproperties = fileNode.NodeProperties as SingleFileGeneratorNodeProperties;

            if (nodeproperties == null)
            {
                throw new InvalidOperationException();
            }

            string customToolProgID = nodeproperties.CustomTool;

            if (string.IsNullOrEmpty(customToolProgID))
            {
                return;
            }

            // not sure what to do if BuildAction is set to "MSBuild:Compile".  IronPython doesn't handle this correctly either.
            // This build action is set for .xaml files but doing nothing doesn't seem to cause problems, so for now we ignore this
            // generator type and do nothing too.  If we don't do this, we get lots of message boxes when the clsid of this non-existent
            // single file generator isn't found.

            // We should try to find out what the proper action is here.  There is no "MSBuild:Compile" entry in the registry
            // for the C# or VB project system single file generators, so there must be some special handling for this build type
            // otherwise it would just be blank.  Naturally, the IronPython sample isn't any help here.

            if (customToolProgID.StartsWith("MSBuild:Compile", StringComparison.OrdinalIgnoreCase))
            {
                var project = fileNode.ProjectMgr as XSharpProjectNode;
                if (project.IsXamlFile(document))
                {
                    // need to generate the .g.prg file.
                    project.Build(project.CurrentConfig.ConfigCanonicalName, "BuildGenerateSources"); //  BuildGenerateSources
                }
                // The C# project system then calls a InvokeMsBuild method with the following contents

                /*
                 * HRESULT CVsProjBaseFileNode::InvokeMSBuildTarget(_In_z_ LPCWSTR wszMSBuildTarget)
                 * {
                 *  HRESULT hr = NOERROR;
                 *
                 *  if (wszMSBuildTarget != NULL)
                 *  {
                 *      CLangBuildMgr *pBuildMgr = GetProject()->GetBuildMgr();
                 *      CComPtr<MSBuildEngine::IProject> srpMSBuildProject = pBuildMgr->GetMSBuildProject();
                 *
                 *      if (CXMakeHelper::DoesTargetExist(srpMSBuildProject, wszMSBuildTarget) && pBuildMgr->HasPassedSecurityChecks())
                 *      {
                 *          // Initialize the build engine for this project and configuration.
                 *          CSmartMSBuildInitializer smsbi;
                 *          CLangProjectConfig *pProjConfig = pBuildMgr->GetConfigs()->GetActiveConfig();
                 *          hr = smsbi.Initialize(pBuildMgr, pProjConfig);
                 *
                 *          if (SUCCEEDED(hr))
                 *          {
                 *              // Build the specified target in the MSBuild project.
                 *              hr = pBuildMgr->BuildTarget(wszMSBuildTarget);
                 *          }
                 *
                 *          // Don't bother keeping the return value here--we want to
                 *          // return failure from Initialize or BuildTarget instead.
                 *          smsbi.Restore(pBuildMgr);
                 *      }
                 *  }
                 *
                 *  return hr;
                 * }
                 */
                return;
            }

            string customToolNamespace = nodeproperties.CustomToolNamespace;

            try
            {
                if (!this.runningGenerator)
                {
                    //Find if any dependent node exists
                    string        dependentNodeName = null;
                    HierarchyNode dependentNode     = fileNode.FirstChild;

                    while (dependentNode != null)
                    {
                        string dependentUpon = dependentNode.ItemNode.GetMetadata(ProjectFileConstants.DependentUpon);

                        if (!String.IsNullOrEmpty(dependentUpon))
                        {
                            if (!Path.IsPathRooted(dependentUpon))
                            {
                                dependentUpon = Path.Combine(Path.GetDirectoryName(fileNode.Url), dependentUpon);
                            }

                            if (string.Compare(dependentUpon, fileNode.Url, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                dependentNodeName = ((FileNode)dependentNode).FileName;
                                break;
                            }
                        }

                        dependentNode = dependentNode.NextSibling;
                    }

                    bool outputOutOfDate = dependentNodeName == null;

                    if ((!runEvenIfNotDirty) && !outputOutOfDate)
                    {
                        string generatedFile = Path.Combine(Path.GetDirectoryName(fileNode.GetMkDocument()), dependentNodeName);

                        outputOutOfDate = !File.Exists(generatedFile);

                        if (!outputOutOfDate)
                        {
                            outputOutOfDate = File.GetLastWriteTime(fileNode.GetMkDocument()) > File.GetLastWriteTime(generatedFile);

                            if (!outputOutOfDate)
                            {
                                IVsHierarchy      rdtHier;
                                IVsPersistDocData perDocData;
                                uint cookie;
                                outputOutOfDate = this.VerifyFileDirtyInRdt(document, out rdtHier, out perDocData, out cookie);
                            }
                        }
                    }

                    //if (runEvenIfNotDirty || outputOutOfDate)
                    {
                        //Get the buffer contents for the current node
                        string moniker = fileNode.GetMkDocument();

                        this.runningGenerator = true;
                        anyGeneratorsRunning++;

                        //Get the generator
                        IVsSingleFileGenerator generator;
                        int generateDesignTimeSource;
                        int generateSharedDesignTimeSource;
                        int generateTempPE;
                        SingleFileGeneratorFactory factory = new SingleFileGeneratorFactory(this.ProjectMgr.ProjectGuid, this.ProjectMgr.Site);
                        ErrorHandler.ThrowOnFailure(factory.CreateGeneratorInstance(customToolProgID, out generateDesignTimeSource, out generateSharedDesignTimeSource, out generateTempPE, out generator));

                        //Check to see if the generator supports siting
                        IObjectWithSite objWithSite = generator as IObjectWithSite;
                        if (objWithSite != null)
                        {
                            objWithSite.SetSite(fileNode.OleServiceProvider);
                        }

                        //Determine the namespace
                        if (string.IsNullOrEmpty(customToolNamespace))
                        {
                            customToolNamespace = this.ComputeNamespace(moniker);
                        }

                        //Run the generator
                        IntPtr[] output = new IntPtr[1];
                        output[0] = IntPtr.Zero;
                        uint outPutSize;

                        if (dependentNodeName == null)
                        {
                            string extension = null;
                            try
                            {
                                generator.DefaultExtension(out extension);
                            }
                            catch (Exception e)
                            {
                                if (System.Diagnostics.Debugger.IsAttached)
                                {
                                    Debug.WriteLine(e);
                                }
                            }
                            if (!String.IsNullOrEmpty(extension))
                            {
                                dependentNodeName = Path.GetFileNameWithoutExtension(fileNode.FileName) + extension;
                            }
                            else
                            {
                                dependentNodeName = fileNode.FileName;
                            }
                        }


                        //If you found a dependent node.
                        if (dependentNode != null)
                        {
                            //Then check out the node and dependent node from SCC
                            if (!this.CanEditFile(dependentNode.GetMkDocument()))
                            {
                                throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED);
                            }
                        }
                        else //It is a new node to be added to the project
                        {
                            // Check out the project file if necessary.
                            if (!this.ProjectMgr.QueryEditProjectFile(false))
                            {
                                throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED);
                            }
                        }
                        IVsTextStream stream;
                        string        inputFileContents = this.GetBufferContents(moniker, out stream);

                        var    res  = generator.Generate(moniker, inputFileContents, customToolNamespace, output, out outPutSize, this);
                        byte[] data = new byte[outPutSize];

                        if (output[0] != IntPtr.Zero)
                        {
                            Marshal.Copy(output[0], data, 0, (int)outPutSize);
                            Marshal.FreeCoTaskMem(output[0]);
                        }

                        //Todo - Create a file and add it to the Project
                        string fileToAdd = this.UpdateGeneratedCodeFile(fileNode, data, (int)outPutSize, dependentNodeName, dependentNode);
                    }
                }
            }
            finally
            {
                this.runningGenerator = false;
                anyGeneratorsRunning--;
            }
        }