public int GetMemberNavigationPoint(string pszClassName, string pszUniqueMemberID, TextSpan[] pSpanNavPoint, out uint pItemID) { // Validate the parameters if (string.IsNullOrEmpty(pszClassName)) { throw new System.ArgumentNullException("pszClassName"); } if (string.IsNullOrEmpty(pszUniqueMemberID)) { throw new System.ArgumentNullException("pszUniqueMemberID"); } if ((null == pSpanNavPoint) || (0 == pSpanNavPoint.Length)) { throw new ArgumentNullException("pSpanNavPoint"); } // Get the implementation class CodeClassInfo implInfo = ImplementationClass(pszClassName); if ((null == implInfo) || (null == implInfo.CodeClass)) { throw new System.ArgumentException("pszClassName"); } EnvDTE.CodeClass implClass = implInfo.CodeClass; // Verify that the unique id is valid. string memberName = MemberNameFromUniqueId(pszUniqueMemberID); if (string.IsNullOrEmpty(memberName)) { throw new System.ArgumentException(); } // Remove the '_' added by the file code model if (memberName[0] == '_') { memberName = memberName.Substring(1); } // Get the code element for the member. EnvDTE.CodeElement member = GetClassMember(implClass, memberName); if (null == member) { throw new System.ArgumentException(); } // Set the output variables. pSpanNavPoint[0] = CodeElementSpan(member); pItemID = implInfo.ItemId; return(VSConstants.S_OK); }
public int CreateUniqueEventName(string pszClassName, string pszObjectName, string pszNameOfEvent, out string pbstrEventHandlerName) { // Get the class that will contain the actual implementation of the event handler. CodeClassInfo implInfo = ImplementationClass(pszClassName); if ((null == implInfo) || (null == implInfo.CodeClass)) { throw new System.ArgumentException("pszClassName"); } EnvDTE.CodeClass implClass = implInfo.CodeClass; // Build the default name for the event handler. string baseName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", pszObjectName, pszNameOfEvent); pbstrEventHandlerName = baseName; // Now we have to check if the implementation class contains another member with the same name. for (int i = 1; ; ++i) { if (null == GetClassMember(implClass, pbstrEventHandlerName)) { // No member with this name. break; } else { // The name is in use. Change it adding a numeric identifier at the end of it. pbstrEventHandlerName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", baseName, i); } } // Add one underscore at the beginning of the function name because this is what the // file code model will add. pbstrEventHandlerName = "_" + pbstrEventHandlerName; // All done, return. return(VSConstants.S_OK); }
public int EnsureEventHandler(string pszClassName, string pszObjectTypeName, string pszNameOfEvent, string pszEventHandlerName, uint itemidInsertionPoint, out string pbstrUniqueMemberID, out string pbstrEventBody, TextSpan[] pSpanInsertionPoint) { if (string.IsNullOrEmpty(pszClassName)) { throw new System.ArgumentNullException("pszClassName"); } if ((null == pSpanInsertionPoint) || (pSpanInsertionPoint.Length == 0)) { throw new System.ArgumentNullException("pSpanInsertionPoint"); } if (string.IsNullOrEmpty(pszEventHandlerName)) { throw new System.ArgumentNullException("pszEventHandlerName"); } // The file code model will create a function name that starts with '_', so we must make // sure that the name of the event handler matches it. if (pszEventHandlerName[0] != '_') { throw new System.ArgumentException("pszEventHandlerName"); } // Given the fact that the file code model will add _ at the beginning of the name, // we have to remove the underscore from the name passed to AddFunction. string handlerName = pszEventHandlerName.Substring(1); // Initialize the out parameters. pbstrUniqueMemberID = null; pbstrEventBody = null; // Get the implementation class. CodeClassInfo implInfo = ImplementationClass(pszClassName); if ((null == implInfo) || (null == implInfo.CodeClass)) { // According with the documentation this method must return E_FAIL if the class does not // exist in this scope. return(VSConstants.E_FAIL); } EnvDTE.CodeClass implClass = implInfo.CodeClass; // Check if the method exists. EnvDTE.CodeElement member = GetClassMember(implClass, handlerName); if (null != member) { // If the member exists this function must return its unique id and insertion point, but the // event body must be null. pbstrUniqueMemberID = ClassMemberUniqueId(implClass, pszEventHandlerName); pSpanInsertionPoint[0] = CodeElementSpan(member); return(VSConstants.S_OK); } // There is no event handler, so we have to create it. EnvDTE.CodeFunction eventHandler = implClass.AddFunction(handlerName, EnvDTE.vsCMFunction.vsCMFunctionFunction, EnvDTE.vsCMTypeRef.vsCMTypeRefVoid, -1, EnvDTE.vsCMAccess.vsCMAccessPrivate, null); eventHandler.AddParameter("sender", EnvDTE.vsCMTypeRef.vsCMTypeRefObject, 1); eventHandler.AddParameter("args", "System.EventArgs", 2); // Make sure that the right document is visible. if (null != eventHandler.ProjectItem) { eventHandler.ProjectItem.Open(System.Guid.Empty.ToString("B")); if (null != eventHandler.ProjectItem.Document) { eventHandler.ProjectItem.Document.Activate(); } } // Set the navigation point pSpanInsertionPoint[0] = CodeElementSpan(eventHandler as EnvDTE.CodeElement); pbstrUniqueMemberID = ClassMemberUniqueId(implClass, pszEventHandlerName); // The HTML editor will remove the initial spaces on the string returned by this function, but // this will break the indentation and the file will not compile. To work around the problem // we create a first line that is a comment, so that its indentation is not a problem. StringBuilder eventBody = new StringBuilder(); eventBody.AppendLine("#"); // Add the actual body of the event handler. eventBody.Append(stringMerger.GetTextFromLine(pSpanInsertionPoint[0].iStartLine - 1)); pbstrEventBody = eventBody.ToString(); return(VSConstants.S_OK); }