Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rearrange project modifier.cs #2040

Merged
merged 4 commits into from
Oct 10, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,139 @@ public async Task AddAuthCodeAsync()
_consoleLogger.LogJsonMessage(new JsonResponse(Commands.UPDATE_PROJECT_COMMAND, State.Success, output: _output.ToString().TrimEnd()));
}

internal static string GetCodeFileString(CodeFile file, string identifier) // todo make all code files strings
{
// Resource files cannot contain '-' (dash) or '.' (period)
var codeFilePropertyName = $"add_{identifier.Replace('-', '_')}_{file.FileName.Replace('.', '_')}";
var property = AppProvisioningTool.Properties.FirstOrDefault(
p => p.Name.Equals(codeFilePropertyName));

if (property is null)
{
throw new FormatException($"Resource property for {file.FileName} could not be found. ");
}

var codeFileString = property.GetValue(typeof(Resources))?.ToString();

if (string.IsNullOrEmpty(codeFileString))
{
throw new FormatException($"CodeFile string for {file.FileName} was empty.");
}

return codeFileString;
}

internal static ClassDeclarationSyntax ModifyMethods(string fileName, ClassDeclarationSyntax classNode, DocumentBuilder documentBuilder, Dictionary<string, Method> methods, CodeChangeOptions options, StringBuilder output)
{
foreach ((string methodName, Method methodChanges) in methods)
{
if (methodChanges == null)
{
continue;
}

var methodNode = ProjectModifierHelper.GetOriginalMethod(classNode, methodName, methodChanges);
if (methodNode is null)
{
continue;
}

var parameters = ProjectModifierHelper.VerifyParameters(methodChanges.Parameters, methodNode.ParameterList.Parameters.ToList());
foreach ((string oldValue, string newValue) in parameters)
{
methodChanges.CodeChanges = ProjectModifierHelper.UpdateVariables(methodChanges.CodeChanges, oldValue, newValue);
}

var updatedMethodNode = DocumentBuilder.GetModifiedMethod(fileName, methodNode, methodChanges, options, output);
if (updatedMethodNode != null)
{
classNode = classNode.ReplaceNode(methodNode, updatedMethodNode);
}
}

return classNode;
}

internal static async Task ModifyCshtmlFile(CodeFile file, CodeAnalysis.Project project, CodeChangeOptions options)
{
var fileDoc = project.Documents.FirstOrDefault(d => d.Name.EndsWith(file.FileName));
if (fileDoc is null || file.Methods is null || !file.Methods.TryGetValue("Global", out var globalMethod))
{
return;
}

var filteredCodeChanges = globalMethod.CodeChanges.Where(cc => ProjectModifierHelper.FilterOptions(cc.Options, options));
if (!filteredCodeChanges.Any())
{
return;
}

// add code snippets/changes.
var editedDocument = await ProjectModifierHelper.ModifyDocumentText(fileDoc, filteredCodeChanges);
if (editedDocument != null)
{
await ProjectModifierHelper.UpdateDocument(editedDocument);
}
}

/// <summary>
/// Updates .razor and .html files via string replacement
/// </summary>
/// <param name="file"></param>
/// <param name="project"></param>
/// <param name="toolOptions"></param>
/// <returns></returns>
internal static async Task ApplyTextReplacements(CodeFile file, CodeAnalysis.Project project, CodeChangeOptions toolOptions)
{
var document = project.Documents.FirstOrDefault(d => d.Name.EndsWith(file.FileName));
if (document is null)
{
return;
}

var replacements = file.Replacements.Where(cc => ProjectModifierHelper.FilterOptions(cc.Options, toolOptions));
if (!replacements.Any())
{
return;
}

var editedDocument = await ProjectModifierHelper.ModifyDocumentText(document, replacements);
if (editedDocument != null)
{
await ProjectModifierHelper.UpdateDocument(editedDocument);
}
}

internal async Task ModifyCsFile(CodeFile file, CodeAnalysis.Project project, CodeChangeOptions options)
{
if (file.FileName.Equals("Startup.cs"))
{
// Startup class file name may be different
file.FileName = await ProjectModifierHelper.GetStartupClass(project.Documents.ToList()) ?? file.FileName;
}

var fileDoc = project.Documents.Where(d => d.Name.EndsWith(file.FileName)).FirstOrDefault();
if (fileDoc is null || string.IsNullOrEmpty(fileDoc.Name))
{
return;
}

// get the file document to get the document root for editing.
DocumentEditor documentEditor = await DocumentEditor.CreateAsync(fileDoc);
if (documentEditor is null)
{
return;
}

DocumentBuilder documentBuilder = new DocumentBuilder(documentEditor, file, _consoleLogger);
var modifiedRoot = ModifyRoot(documentBuilder, options, file);
if (modifiedRoot != null)
{
documentEditor.ReplaceNode(documentEditor.OriginalRoot, modifiedRoot);
await documentBuilder.WriteToClassFileAsync(fileDoc.Name);
}
}

private CodeModifierConfig? GetCodeModifierConfig()
{
if (string.IsNullOrEmpty(_toolOptions.ProjectType))
Expand Down Expand Up @@ -208,58 +341,6 @@ private void AddFile(CodeFile file, string identifier)
}
}

internal static string GetCodeFileString(CodeFile file, string identifier) // todo make all code files strings
{
// Resource files cannot contain '-' (dash) or '.' (period)
var codeFilePropertyName = $"add_{identifier.Replace('-', '_')}_{file.FileName.Replace('.', '_')}";
var property = AppProvisioningTool.Properties.FirstOrDefault(
p => p.Name.Equals(codeFilePropertyName));

if (property is null)
{
throw new FormatException($"Resource property for {file.FileName} could not be found. ");
}

var codeFileString = property.GetValue(typeof(Resources))?.ToString();

if (string.IsNullOrEmpty(codeFileString))
{
throw new FormatException($"CodeFile string for {file.FileName} was empty.");
}

return codeFileString;
}

internal async Task ModifyCsFile(CodeFile file, CodeAnalysis.Project project, CodeChangeOptions options)
{
if (file.FileName.Equals("Startup.cs"))
{
// Startup class file name may be different
file.FileName = await ProjectModifierHelper.GetStartupClass(project.Documents.ToList()) ?? file.FileName;
}

var fileDoc = project.Documents.Where(d => d.Name.EndsWith(file.FileName)).FirstOrDefault();
if (fileDoc is null || string.IsNullOrEmpty(fileDoc.Name))
{
return;
}

// get the file document to get the document root for editing.
DocumentEditor documentEditor = await DocumentEditor.CreateAsync(fileDoc);
if (documentEditor is null)
{
return;
}

DocumentBuilder documentBuilder = new DocumentBuilder(documentEditor, file, _consoleLogger);
var modifiedRoot = ModifyRoot(documentBuilder, options, file);
if (modifiedRoot != null)
{
documentEditor.ReplaceNode(documentEditor.OriginalRoot, modifiedRoot);
await documentBuilder.WriteToClassFileAsync(fileDoc.Name);
}
}

/// <summary>
/// Modifies root if there any applicable changes
/// </summary>
Expand Down Expand Up @@ -324,86 +405,5 @@ internal async Task ModifyCsFile(CodeFile file, CodeAnalysis.Project project, Co

return root;
}

private static ClassDeclarationSyntax ModifyMethods(string fileName, ClassDeclarationSyntax classNode, DocumentBuilder documentBuilder, Dictionary<string, Method> methods, CodeChangeOptions options, StringBuilder output)
{
foreach ((string methodName, Method methodChanges) in methods)
{
if (methodChanges == null)
{
continue;
}

var methodNode = ProjectModifierHelper.GetOriginalMethod(classNode, methodName, methodChanges);
if (methodNode is null)
{
continue;
}

var parameters = ProjectModifierHelper.VerifyParameters(methodChanges.Parameters, methodNode.ParameterList.Parameters.ToList());
foreach ((string oldValue, string newValue) in parameters)
{
methodChanges.CodeChanges = ProjectModifierHelper.UpdateVariables(methodChanges.CodeChanges, oldValue, newValue);
}

var updatedMethodNode = DocumentBuilder.GetModifiedMethod(fileName, methodNode, methodChanges, options, output);
if (updatedMethodNode != null)
{
classNode = classNode.ReplaceNode(methodNode, updatedMethodNode);
}
}

return classNode;
}

internal async Task ModifyCshtmlFile(CodeFile file, CodeAnalysis.Project project, CodeChangeOptions options)
{
var fileDoc = project.Documents.FirstOrDefault(d => d.Name.EndsWith(file.FileName));
if (fileDoc is null || file.Methods is null || !file.Methods.TryGetValue("Global", out var globalMethod))
{
return;
}

var filteredCodeChanges = globalMethod.CodeChanges.Where(cc => ProjectModifierHelper.FilterOptions(cc.Options, options));
if (!filteredCodeChanges.Any())
{
return;
}

// add code snippets/changes.
var editedDocument = await ProjectModifierHelper.ModifyDocumentText(fileDoc, filteredCodeChanges);
if (editedDocument != null)
{
await ProjectModifierHelper.UpdateDocument(editedDocument);
}
}

/// <summary>
/// Updates .razor and .html files via string replacement
/// </summary>
/// <param name="file"></param>
/// <param name="project"></param>
/// <param name="toolOptions"></param>
/// <returns></returns>
internal async Task ApplyTextReplacements(CodeFile file, CodeAnalysis.Project project, CodeChangeOptions toolOptions)
{
var document = project.Documents.FirstOrDefault(d => d.Name.EndsWith(file.FileName));
if (document is null)
{
return;
}

var replacements = file.Replacements.Where(cc => ProjectModifierHelper.FilterOptions(cc.Options, toolOptions));
if (!replacements.Any())
{
return;
}

var editedDocument = await ProjectModifierHelper.ModifyDocumentText(document, replacements);
if (editedDocument != null)
{
await ProjectModifierHelper.UpdateDocument(editedDocument);
}
}
}
}