I'm trying to make my own Move to Resource refactoring (like the one found in ReSharper). In my CodeAction.GetChangedDocumentAsync
method I'm doing these 3 steps:
- Add my resource to the Resources.resx file with
XmlDocument
- Use DTE to run the custom tool to update the Resources.Designer.cs file
- Replace the literal string by the qualified identifier of the new resource with
SyntaxNode.ReplaceNode
Steps 1 & 2 are OK, but 3 does not work. If I remove the step 2, 3 is working.
I don't know if it is because I'm mixing Roslyn & DTE or if it's because step 2 generate new code in the solution and my cached context becomes invalid.
// Add the resource to the Resources.resx file
var xmlDoc = new XmlDocument();
xmlDoc.Load(resxPath);
XmlNode node = xmlDoc.SelectSingleNode($"//data[@name='{resourceIndentifierName}']");
if (node != null) return;
XmlElement dataElement = xmlDoc.CreateElement("data");
XmlAttribute nameAtt = xmlDoc.CreateAttribute("name");
nameAtt.Value = resourceIndentifierName;
dataElement.Attributes.Append(nameAtt);
XmlAttribute spaceAtt = xmlDoc.CreateAttribute("space", "xml");
spaceAtt.Value = "preserve";
dataElement.Attributes.Append(spaceAtt);
XmlElement valueElement = xmlDoc.CreateElement("value");
valueElement.InnerText = value;
dataElement.AppendChild(valueElement);
XmlNode rootNode = xmlDoc.SelectSingleNode("//root");
Debug.Assert(rootNode != null, "rootNode != null");
rootNode.AppendChild(dataElement);
xmlDoc.Save(resxPath);
// Update the Resources.Designer.cs file
var dte = (DTE2)Package.GetGlobalService(typeof(SDTE));
ProjectItem item = dte.Solution.FindProjectItem(resxPath);
((VSProjectItem) item.Object)?.RunCustomTool();
// Replace the node
SyntaxNode oldRoot = await context.Document.GetSyntaxRootAsync(cancellationToken)
.ConfigureAwait(false);
SyntaxNode newRoot = oldRoot.ReplaceNode(oldNode, newNode);
return context.Document.WithSyntaxRoot(newRoot);