/// <summary>Finds all instances of a text in the document object for the provided item.</summary> /// <param name="item">Project item to search texts</param> /// <param name="text">Text to look for</param> /// <returns>A collection of BaseHardCodedString objects that references to text</returns> public static ReadOnlyCollection <BaseHardCodedString> FindAllInstancesInDocument(ProjectItem item, string text) { TextDocument doc = GetDocumentForItem(item); Collection <BaseHardCodedString> instances = new Collection <BaseHardCodedString>(); EditPoint start = doc.StartPoint.CreateEditPoint(); start.MoveToAbsoluteOffset(1); EditPoint end = null; // Unused object for FindPattern method. TextRanges ranges = null; System.Collections.IEnumerator comments = null; Match currentMatch = null; BaseHardCodedString instance = BaseHardCodedString.GetHardCodedString(item.Document); while (start.FindPattern(text, (int)(vsFindOptions.vsFindOptionsMatchCase), ref end, ref ranges)) { if (instance != null) { if (comments == null) { comments = instance.FindCommentsInDocument(item).GetEnumerator(); } bool inComment = false; while (currentMatch != null || (comments.MoveNext())) { currentMatch = (Match)(comments.Current); // If this match appears earlier then current text skip if (currentMatch.Index + currentMatch.Length <= (start.AbsoluteCharOffset - 1)) { currentMatch = null; } // If this comment is later then current text stop processing comments else if (currentMatch.Index >= (end.AbsoluteCharOffset - 1)) { break; } // At this point current text must be part of a comment block else { inComment = true; break; } } if (!inComment) { instance = instance.CreateInstance(item, start.AbsoluteCharOffset - 1, end.AbsoluteCharOffset - 1); instances.Add(instance); } } start = end; } return(new ReadOnlyCollection <BaseHardCodedString>(instances)); }
/// <summary>Gets the correct <see cref="IExtractResource"/> action implementation for the provided string instance</summary> /// <param name="instance">String instance to refactor</param> /// <returns>an <see cref="IExtractResourceAction"/> implementation. null if no suitable action is found.</returns> public static IExtractResourceAction GetExtractResourceActionObject(BaseHardCodedString instance) { if (actionObjectCache.ContainsKey(instance.Parent)) { return(actionObjectCache[instance.Parent]); } if (availableActionObjectList == null) { availableActionObjectList = new List <IExtractResourceAction>(); Assembly currentAssembly = Assembly.GetExecutingAssembly(); Type[] types = currentAssembly.GetTypes(); foreach (Type type in types) { if (!type.IsAbstract && (typeof(IExtractResourceAction)).IsAssignableFrom(type)) { try { IExtractResourceAction currentAction = System.Activator.CreateInstance(type) as IExtractResourceAction; if (currentAction != null) { availableActionObjectList.Add(currentAction); } } catch (TargetInvocationException e) { System.Diagnostics.Trace.TraceError(e.ToString()); } catch (ArgumentException e) { System.Diagnostics.Trace.TraceError(e.ToString()); } catch (MissingMethodException e) { System.Diagnostics.Trace.TraceError(e.ToString()); } } } } IExtractResourceAction action = null; foreach (IExtractResourceAction currentAction in availableActionObjectList) { if (!currentAction.QuerySupportForProject(instance.Parent)) { continue; } if (action == null || currentAction.Priority > action.Priority) { action = currentAction; } } if (action != null) { if (actionObjectCache.Count > 30) { actionObjectCache.Clear(); } actionObjectCache.Add(instance.Parent, action); } return(action); }
private void PerformAction(Common.BaseHardCodedString stringInstance) { ExtractToResourceActionSite site = new ExtractToResourceActionSite(stringInstance); if (site.ActionObject != null) { RefactorStringDialog dialog = new RefactorStringDialog(); dialog.ShowDialog(site); } else { MessageBox.Show(Strings.UnsupportedFile, Strings.WarningTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
public void Exec(string cmdName, vsCommandExecOption executeOption, ref object variantIn, ref object variantOut, ref bool handled) { if (cmdName == null) { throw new ArgumentNullException("CmdName"); } if (cmdName == typeof(Connect).FullName + "." + Strings.RefactorCommandName) { TextSelection selection = (TextSelection)(applicationObject.ActiveDocument.Selection); if (applicationObject.ActiveDocument.ProjectItem.Object != null) { Common.BaseHardCodedString stringInstance = BaseHardCodedString.GetHardCodedString(applicationObject.ActiveDocument); if (stringInstance == null) { MessageBox.Show( Strings.UnsupportedFile + " (" + applicationObject.ActiveDocument.Language + ")", Strings.WarningTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Common.MatchResult scanResult = stringInstance.CheckForHardCodedString( selection.Parent, selection.AnchorPoint.AbsoluteCharOffset - 1, selection.BottomPoint.AbsoluteCharOffset - 1); if (!scanResult.Result && selection.AnchorPoint.AbsoluteCharOffset < selection.BottomPoint.AbsoluteCharOffset) { scanResult.StartIndex = selection.AnchorPoint.AbsoluteCharOffset - 1; scanResult.EndIndex = selection.BottomPoint.AbsoluteCharOffset - 1; scanResult.Result = true; } if (scanResult.Result) { stringInstance = stringInstance.CreateInstance(applicationObject.ActiveDocument.ProjectItem, scanResult.StartIndex, scanResult.EndIndex); if (stringInstance != null && stringInstance.Parent != null) { PerformAction(stringInstance); } } else { MessageBox.Show(Strings.NotStringLiteral, Strings.WarningTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } }
/// <summary>CTor - creates a new generic hard coded string pointer.</summary> /// <param name="parent">Reference to code file containing the string</param> /// <param name="lineNumber">Line number</param> /// <param name="start">Starting index (including quotes, with 0 indexing)</param> /// <param name="end">Ending index (including quotes)</param> protected BaseHardCodedString(ProjectItem parent, int start, int end) : this() { this.parent = parent; TextDocument doc = BaseHardCodedString.GetDocumentForItem(parent); this.beginEditPoint = doc.StartPoint.CreateEditPoint(); if (start < Int32.MaxValue) { start++; } if (end < Int32.MaxValue) { end++; } this.beginEditPoint.MoveToAbsoluteOffset(start); this.endEditPoint = doc.StartPoint.CreateEditPoint(); this.endEditPoint.MoveToAbsoluteOffset(end); this.textLength = end - start; }
/// <summary> /// Returns an instance of BaseHardCodedString, based the type of the current document. /// </summary> /// <param name="currentDocument">The document that contains an hard-coded string.</param> /// <returns>A hard coded string that is file type aware.</returns> public static BaseHardCodedString GetHardCodedString(Document currentDocument) { BaseHardCodedString stringInstance = null; // Create the hard coded string instance switch (currentDocument.Language) { case "CSharp": stringInstance = new CSharpHardCodedString(); break; case "Basic": stringInstance = new VBHardCodedString(); break; case "XAML": stringInstance = new XamlHardCodedString(); break; case "HTMLX": if (currentDocument.Name.EndsWith(".cshtml", StringComparison.CurrentCultureIgnoreCase)) { stringInstance = new CSharpRazorHardCodedString(); } else if (currentDocument.Name.EndsWith(".vbhtml", StringComparison.CurrentCultureIgnoreCase)) { stringInstance = new VBRazorHardCodedString(); } break; case "HTML": if (currentDocument.Name.EndsWith(".aspx", StringComparison.CurrentCultureIgnoreCase) || currentDocument.Name.EndsWith(".ascx", StringComparison.CurrentCultureIgnoreCase) || currentDocument.Name.EndsWith(".master", StringComparison.CurrentCultureIgnoreCase)) { stringInstance = new AspxHardCodedString(); } break; } return(stringInstance); }
/// <summary> /// Gets the correct ExtractResource action implementation for the provided string instance /// </summary> /// <param name="instance">String instance to refactor</param> /// <returns>an IExtractResourceAction implementation. null if no suitable action is found.</returns> public static IExtractResourceAction GetExtractResourceActionObject(BaseHardCodedString instance) { if (actionObjectCache.ContainsKey(instance.Parent)) return actionObjectCache[instance.Parent]; if (availableActionObjectList == null) { availableActionObjectList = new List<IExtractResourceAction>(); Assembly currentAssembly = Assembly.GetExecutingAssembly(); Type[] types = currentAssembly.GetTypes(); foreach (Type type in types) { if (!type.IsAbstract && (typeof(IExtractResourceAction)).IsAssignableFrom(type)) { try { IExtractResourceAction currentAction = System.Activator.CreateInstance(type) as IExtractResourceAction; if (currentAction != null) { availableActionObjectList.Add(currentAction); } } catch (TargetInvocationException e) { System.Diagnostics.Trace.TraceError(e.ToString()); } catch (ArgumentException e) { System.Diagnostics.Trace.TraceError(e.ToString()); } catch (MissingMethodException e) { System.Diagnostics.Trace.TraceError(e.ToString()); } } } } IExtractResourceAction action = null; foreach (IExtractResourceAction currentAction in availableActionObjectList) { if (!currentAction.QuerySupportForProject(instance.Parent)) { continue; } if (action == null || currentAction.Priority > action.Priority) { action = currentAction; } } if (action != null) { if (actionObjectCache.Count > 30) actionObjectCache.Clear(); actionObjectCache.Add(instance.Parent, action); } return action; }
/// <summary> /// Invokes replace method on the provided objects /// </summary> /// <param name="codeFile">Code file to test</param> /// <param name="resFile">Resource file to use</param> /// <param name="hcs">Hardcoded string to use</param> /// <param name="expected">Expected test string</param> internal static void TestReplaceMethod(ProjectItem codeFile, string resourceFileName, BaseHardCodedString hcs, string expected, string resourceName) { string fileName = codeFile.get_FileNames(1); bool readOnly = false; try { readOnly = CommonMethods.ToggleReadOnly(fileName, false); ExtractToResourceActionSite refactorSite = new ExtractToResourceActionSite(hcs); ResourceFileCollection resources = new ResourceFileCollection(codeFile.ContainingProject, new FilterMethod(refactorSite.ActionObject.IsValidResourceFile)); ResourceFile resFile = resources[resourceFileName]; refactorSite.ExtractStringToResource(resFile, resourceName); TextDocument doc = ((EnvDTE.TextDocument)codeFile.Document.Object(null)); EditPoint ep = doc.StartPoint.CreateEditPoint(); string line = ep.GetLines(hcs.StartingLine + 1, hcs.StartingLine + 2); Assert.AreEqual(expected, line, "New line does not match the expected output"); } finally { if (readOnly) CommonMethods.ToggleReadOnly(fileName, true); } }
/// <summary>Returns the code reference to resource specified in the parameters</summary> /// <param name="file">Resource file containing the resource</param> /// <param name="resourceName">Name of the resource</param> /// <returns>a piece of code that would reference to the resource provided</returns> /// <remarks>This method does not verify if resource actually exists</remarks> public override string GetResourceReference(ResourceFile file, string resourceName, Project project, BaseHardCodedString @string) { if (@string.Value.StartsWith("\"") || @string.Value.StartsWith("'")) { return(string.Format("{0}<%$ Resources:{1}, {2} %>{0}", @string.Value[0], Path.GetFileNameWithoutExtension(file.FileName), resourceName)); } else { return(string.Format("<asp:Literal ruant=\"server\" Text=\"<%$ Resources:{0}, {1} %>\" Mode=\"Encode\"/>", Path.GetFileNameWithoutExtension(file.FileName), resourceName)); } }
/// <summary>Returns the code reference to resource specified in the parameters</summary> /// <param name="file">Resource file containing the resource</param> /// <param name="resourceName">Name of the resource</param> /// <returns>a piece of code that would reference to the resource provided</returns> /// <remarks>This method does not verify if resource actually exists</remarks> public override string GetResourceReference(ResourceFile file, string resourceName, Project project, BaseHardCodedString @string) { if (file == null) { throw new ArgumentNullException("file"); } if (String.IsNullOrEmpty(resourceName)) { throw new ArgumentException(Strings.InvalidResourceName, "resourceName"); } string namespacePrefix = GetNamespacePrefix(file); if (!file.IsDefaultResXFile()) { namespacePrefix += Path.GetFileNameWithoutExtension(file.ShortFileName).Replace(' ', '_') + "."; } string reference = namespacePrefix + resourceName.Replace(' ', '_'); return(reference); }
/// <summary>When overriden in derived class returns the code reference to resource specified in the parameters</summary> /// <param name="file">Resource file containing the resource</param> /// <param name="resourceName">Name of the resource</param> /// <param name="project">Project current file belongs to</param> /// <param name="string">String being extracted</param> /// <returns>a piece of code that would reference to the resource provided</returns> /// <remarks>This method does not verify if resource actually exists</remarks> public abstract string GetResourceReference(ResourceFile file, string resourceName, Project project, BaseHardCodedString @string);
/// <summary> /// Creates a new instance to refactor provided string instance /// </summary> /// <param name="stringInstance">String instance to refactor</param> public ExtractToResourceActionSite(BaseHardCodedString stringInstance) { this.stringInstance = stringInstance; actionObject = GetExtractResourceActionObject(this.StringToExtract); }
/// <summary>Creates a new instance to refactor provided string instance</summary> /// <param name="stringInstance">String instance to refactor</param> public ExtractToResourceActionSite(BaseHardCodedString stringInstance) { this.stringInstance = stringInstance; actionObject = GetExtractResourceActionObject(this.StringToExtract); }
/// <summary>Returns the code reference to resource specified in the parameters</summary> /// <param name="file">Resource file containing the resource</param> /// <param name="resourceName">Name of the resource</param> /// <param name="project">Project current file belongs to</param> /// <param name="string">String being extracted</param> /// <returns>a piece of code that would reference to the resource provided</returns> /// <remarks>This method does not verify if resource actually exists</remarks> public override string GetResourceReference(ResourceFile file, string resourceName, Project project, BaseHardCodedString @string) { string prefix = ""; if (ExtensibilityMethods.GetProjectType(project) == ProjectType.VB) { try { prefix = (string)project.Properties.Item("RootNamespace").Value; if (!string.IsNullOrEmpty(prefix)) { prefix += "."; } } catch { } } if (file == null) { throw new ArgumentNullException("file"); } if (String.IsNullOrEmpty(resourceName)) { throw new ArgumentException(Strings.InvalidResourceName, "resourceName"); } string namespacePrefix = GetNamespacePrefix(file); if (!file.IsDefaultResXFile()) { namespacePrefix += Path.GetFileNameWithoutExtension(file.ShortFileName).Replace(' ', '_') + "."; } else { namespacePrefix += Path.GetFileNameWithoutExtension(file.FileName).Replace(' ', '_') + "."; } string reference = namespacePrefix + resourceName.Replace(' ', '_'); return(prefix + reference); }
/// <summary> /// Queries the implementation to check if string instance is supported /// </summary> /// <param name="stringInstance">String instance to check for</param> /// <returns>True if string is supported</returns> public bool QuerySupportForString(BaseHardCodedString stringInstance) { return stringInstance is CSharpHardCodedString || stringInstance is VBHardCodedString || stringInstance is XamlHardCodedString || stringInstance is CSharpRazorHardCodedString; }