4 Star 3 Fork 2

xiaolu6t6t / NFinal2Compiler

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
NFinalCompilerService.cs 24.23 KB
一键复制 编辑 原始数据 按行查看 历史
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using EnvDTE;
using EnvDTE80;
using System.IO;
using Microsoft.VisualStudio.Shell;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.LanguageServices;
using Microsoft.VisualStudio.ComponentModelHost;
using Task = System.Threading.Tasks.Task;
using Microsoft.VisualStudio.Threading;
using System.Runtime.InteropServices;
namespace NFinalCompiler
{
public class NFinalCompilerService
{
private DTE2 _dte;
public NFinalCompilerAsyncPackage _instance;
public EnvDTE.SolutionEvents _solutionEvents;
public EnvDTE.DocumentEvents _documentEvents;
public VisualStudioWorkspace workspace;
public Config.nfinalextension nfinalextension = null;
public IComponentModel componentModel = null;
public string projectName = null;
public void Initialize(IServiceProvider provider)
{
_dte = provider.GetService(typeof(EnvDTE.DTE)) as DTE2;
EnvDTE80.Events2 events = _dte.Events as Events2;
NFinalCompiler.Helper.ProjectHelpers._dte = _dte;
_documentEvents = events.DocumentEvents;
_solutionEvents = events.SolutionEvents;
events.BuildEvents.OnBuildBegin += BuildEvents_OnBuildBegin;
events.BuildEvents.OnBuildDone += BuildEvents_OnBuildDone;
events.BuildEvents.OnBuildProjConfigBegin += BuildEvents_OnBuildProjConfigBegin;
events.BuildEvents.OnBuildProjConfigDone += BuildEvents_OnBuildProjConfigDone;
_documentEvents.DocumentSaved += DocumentEvents_DocumentSaved;
_solutionEvents.AfterClosing += _solutionEvents_AfterClosing;
_solutionEvents.ProjectRemoved += _solutionEvents_ProjectRemoved;
componentModel =
(IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel));
}
public async Task InitializeAsync(IAsyncServiceProvider provider,CancellationToken cancellationToken)
{
_dte = await provider.GetServiceAsync(typeof(EnvDTE.DTE)) as DTE2;
EnvDTE80.Events2 events = _dte.Events as Events2;
NFinalCompiler.Helper.ProjectHelpers._dte = _dte;
_documentEvents = events.DocumentEvents;
_solutionEvents = events.SolutionEvents;
events.BuildEvents.OnBuildBegin += BuildEvents_OnBuildBegin;
events.BuildEvents.OnBuildDone += BuildEvents_OnBuildDone;
events.BuildEvents.OnBuildProjConfigBegin += BuildEvents_OnBuildProjConfigBegin;
events.BuildEvents.OnBuildProjConfigDone += BuildEvents_OnBuildProjConfigDone;
_documentEvents.DocumentSaved += DocumentEvents_DocumentSaved;
_solutionEvents.AfterClosing += _solutionEvents_AfterClosing;
_solutionEvents.ProjectRemoved += _solutionEvents_ProjectRemoved;
componentModel =
(IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel));
}
private void _solutionEvents_ProjectRemoved(EnvDTE.Project Project)
{
}
private void _solutionEvents_AfterClosing()
{
}
private void BuildEvents_OnBuildProjConfigDone(string Project, string ProjectConfig, string Platform, string SolutionConfig, bool Success)
{
//得到当前编译项目的项目文件名
string solutionName = _dte.Solution.FullName;
projectName = Path.Combine(Path.GetDirectoryName(solutionName), Project);
foreach (dynamic project in _dte.Solution.Projects)
{
if (project.UniqueName == Project)
{
projectName = project.FullName;
}
}
//throw new NotImplementedException();
}
private void BuildEvents_OnBuildBegin(vsBuildScope Scope, vsBuildAction Action)
{
if (vsBuildAction.vsBuildActionBuild == Action || vsBuildAction.vsBuildActionRebuildAll == Action)
{
if (vsBuildScope.vsBuildScopeProject == Scope)
{
}
}
}
private void BuildEvents_OnBuildProjConfigBegin(string Project, string ProjectConfig, string Platform, string SolutionConfig)
{
string solutionName = _dte.Solution.FullName;
projectName = Path.Combine(Path.GetDirectoryName(solutionName), Project);
foreach (dynamic project in _dte.Solution.Projects)
{
if (project.UniqueName == Project)
{
projectName = project.FullName;
}
}
nfinalextension = GetConfig(projectName);
}
private void BuildEvents_OnBuildDone(vsBuildScope Scope, vsBuildAction Action)
{
if (vsBuildAction.vsBuildActionBuild == Action || vsBuildAction.vsBuildActionRebuildAll == Action)
{
if (vsBuildScope.vsBuildScopeProject == Scope)
{
if (nfinalextension.CopyApplication)
{
//Project
StreamReader sr = new StreamReader(projectName, System.Text.Encoding.UTF8);
string projectFileContent = sr.ReadToEnd();
sr.Dispose();
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("<OutputPath>(\\S+)</OutputPath>");
string outPutPath = reg.Match(projectFileContent).Groups[1].Value;
if (outPutPath == string.Empty)
{
outPutPath = "bin\\Debug\\";
}
string FullOutPutPath = Path.Combine(Path.GetDirectoryName(projectName), outPutPath);
System.Text.RegularExpressions.Regex regframework = new System.Text.RegularExpressions.Regex("<TargetFramework>(\\S+)</TargetFramework>");
System.Text.RegularExpressions.Group groupframework = regframework.Match(projectFileContent).Groups[1];
string repairFullOutPutPath = null;
if (groupframework.Success)
{
repairFullOutPutPath = Path.Combine(FullOutPutPath, groupframework.Value);
if (Directory.Exists(repairFullOutPutPath))
{
FullOutPutPath = repairFullOutPutPath;
}
}
string FullCopyPath = Path.Combine(Path.GetDirectoryName(projectName), "bin\\");
//复制文件添加Razor自动提示功能
CopyRazorLibrary(projectName, projectFileContent);
if (FullOutPutPath != FullCopyPath)
{
CopyDirectory(FullOutPutPath, FullCopyPath);
OutPutString("从目录:\"" + FullOutPutPath + "\"复制到:\"" + FullCopyPath + "\"", true);
}
}
}
}
}
private void OutPutString(string str, bool clear = false)
{
OutputWindowPane pane = (_dte as DTE2).ToolWindows.OutputWindow.ActivePane;
pane?.OutputString("NFinalExtension:" + str + "\r\n");
}
private NFinalCompiler.Config.nfinalextension GetConfig(string projectFileName)
{
System.Text.Encoding encoding = new System.Text.UTF8Encoding(false);
string configFileName = Path.GetDirectoryName(projectFileName);
configFileName = Path.Combine(configFileName, "nfinalextension.json");
string json = null;
Config.nfinalextension nfinalextension = null;
if (File.Exists(configFileName))
{
using (StreamReader reader = new StreamReader(configFileName, encoding))
{
try
{
json = reader.ReadToEnd();
nfinalextension = Newtonsoft.Json.JsonConvert.DeserializeObject<NFinalCompiler.Config.nfinalextension>(json);
return nfinalextension;
}
catch (Exception ex)
{
json = null;
OutPutString($"nfinalextension.json解析错误:{ex.Message}");
}
}
}
if (json == null)
{
json = encoding.GetString(NFinalCompiler.Config.Resource1.nfinalextension_nf);
File.WriteAllText(configFileName, json, encoding);
}
json = DeleteComment(json);
nfinalextension = Newtonsoft.Json.JsonConvert.DeserializeObject<NFinalCompiler.Config.nfinalextension>(json);
return nfinalextension;
}
/// <summary>
/// 删除Json配置中的注释,以免解释失败
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static string DeleteComment(string source)
{
System.Text.RegularExpressions.Regex commentRegex =
new System.Text.RegularExpressions.Regex("(^//[^\r\n]*|[^:]//[^\r\n]*)");
source = commentRegex.Replace(source, string.Empty);
return source;
}
public static string GetNameSpace(EnvDTE.Document Document)
{
var project = Document.ProjectItem.ContainingProject;
string nameSpace = Path.Combine(project.Name) + "." +
string.Join(".", Path.GetDirectoryName(Document.ProjectItem.FileNames[0]).Substring(Path.GetDirectoryName(project.FullName).Length).Split(Path.DirectorySeparatorChar)).Trim('.');
nameSpace = nameSpace.TrimEnd('.');
return nameSpace;
}
public static void CopyRazorLibrary(string projectName, string projectFileContent)
{
string binFolder = Path.Combine(Path.GetDirectoryName(projectName), "bin\\");
bool isFrameWork = false;
if (projectFileContent.IndexOf("<TargetFrameworkVersion>") > -1)
{
isFrameWork = true;
}
string fileName;
byte[] buffer;
if (isFrameWork)
{
fileName = Path.Combine(binFolder, "System.Web.Razor.dll");
buffer = RazorLibrary.Resource.System_Web_Razor;
if (!File.Exists(fileName))
{
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}
}
fileName = Path.Combine(binFolder, "System.Runtime.dll");
buffer = RazorLibrary.Resource.System_Runtime;
if (!File.Exists(fileName))
{
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}
}
}
else
{
fileName = Path.Combine(binFolder, "NFinal.dll");
buffer = RazorLibrary.Resource.NFinal;
if (!File.Exists(fileName))
{
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}
}
fileName = Path.Combine(binFolder, "Microsoft.AspNetCore.Razor.dll");
buffer = RazorLibrary.Resource.Microsoft_AspNetCore_Razor;
if (!File.Exists(fileName))
{
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}
}
fileName = Path.Combine(binFolder, "Microsoft.AspNetCore.Runtime.dll");
buffer = RazorLibrary.Resource.Microsoft_AspNetCore_Runtime;
if (!File.Exists(fileName))
{
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}
}
}
}
void CopyDirectory(string SourcePath, string DestinationPath)
{
//创建所有目录
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
//复制所有文件
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
try
{
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);
}
catch
{
continue;
}
}
private void DocumentEvents_DocumentSaved(EnvDTE.Document Document)
{
EnvDTE.Project project;
Microsoft.CodeAnalysis.Project proj;
string projectFileName = Document.ProjectItem.ContainingProject.FullName;
nfinalextension = GetConfig(projectFileName);
//string fileName = null;
if (Document.Name.EndsWith("Controller.cs", StringComparison.OrdinalIgnoreCase))
{
if (!nfinalextension.ControllerModelGenerate)
{
return;
}
project = Document.ProjectItem.ContainingProject;
string parentName = Document.ProjectItem.Name;
string parentFileName = Document.ProjectItem.FileNames[0];
string parentPath = Path.GetDirectoryName(parentFileName);
workspace = componentModel.GetService<VisualStudioWorkspace>();
proj = workspace.CurrentSolution.Projects.Where(doc => doc.FilePath == project.FileName).FirstOrDefault();
CSharpCompilation cSharpCompilation = null;
Compilation compilation = null;
if (cSharpCompilation == null)
{
if (proj.TryGetCompilation(out compilation))
{
cSharpCompilation = (CSharpCompilation)compilation;
}
else
{
cSharpCompilation = (CSharpCompilation)proj.GetCompilationAsync().Result;
}
}
string structFileName = Path.Combine(parentPath, Path.GetFileNameWithoutExtension(parentName) + ".model.cs");
ProjectItem projectItem = Helper.ProjectHelpers.FindInProject(structFileName);
projectItem?.Document?.Close(vsSaveChanges.vsSaveChangesNo);
//projectItem?.Remove();
using (StreamWriter sw = new StreamWriter(structFileName, false, System.Text.Encoding.UTF8))
{
var document = proj.Documents.Single(doc => { return doc.FilePath == parentFileName; });
Controller.StructModel model = new Controller.StructModel();
var tree = document.GetSyntaxTreeAsync().Result;
SyntaxNode root = tree.GetRoot();
SemanticModel semanticModel = cSharpCompilation.GetSemanticModel(tree);
model.WriteDocument(sw, tree, semanticModel);
sw.Close();
OutPutString("生成控制器实体类成功:\"" + structFileName + "\"");
}
if (File.Exists(structFileName))
{
Helper.ProjectHelpers.AddNestedFile(Document.ProjectItem, structFileName, "Compile", false);
}
}
else if (Document.Name.EndsWith(".razor"))
{
if (!nfinalextension.RazorTemplateGenerate)
{
return;
}
project = Document.ProjectItem.ContainingProject;
string parentName = Document.ProjectItem.Name;
string parentFileName = Document.ProjectItem.FileNames[0];
string parentPath = Path.GetDirectoryName(parentFileName);
workspace = componentModel.GetService<VisualStudioWorkspace>();
proj = workspace.CurrentSolution.Projects.Where(doc => doc.FilePath == project.FileName).FirstOrDefault();
string fileName = Path.Combine(parentPath, Path.GetFileNameWithoutExtension(parentName) + ".razor.cs");
ProjectItem projectItem = Helper.ProjectHelpers.FindInProject(fileName);
projectItem?.Document?.Close(vsSaveChanges.vsSaveChangesNo);
projectItem?.Remove();
Document.ProjectItem.ContainingProject.Save();
using (StreamWriter sw = new StreamWriter(fileName, false, System.Text.Encoding.UTF8))
{
string nameSpace = GetNameSpace(Document);
string className = Path.GetFileNameWithoutExtension(parentName);
Razor.RazorWriter writer = new Razor.RazorWriter(parentFileName);
writer.WriteTemplate(sw, nameSpace, className);
sw.Close();
OutPutString("生成模板类成功:\"" + fileName + "\"");
}
if (File.Exists(fileName))
{
projectItem = Helper.ProjectHelpers.AddNestedFile(Document.ProjectItem, fileName, "Compile", false);
//添加<Content Include="Views\Index.cshtml">BrowseToURL
workspace.TryApplyChanges(proj.Solution);
//代码结构
projectItem?.Document?.NewWindow();
workspace = componentModel.GetService<VisualStudioWorkspace>();
proj = workspace.CurrentSolution.Projects.Where(x => x.FilePath == project.FileName).FirstOrDefault();
Microsoft.CodeAnalysis.Document codeDocument = proj.Documents.FirstOrDefault((doc => { if (doc.FilePath == fileName) { return true; } else { return false; } }));
if (codeDocument != null)
{
//格式化
Microsoft.CodeAnalysis.Document formatDocument = Microsoft.CodeAnalysis.Formatting.Formatter.FormatAsync(codeDocument).Result;
//更改
workspace.TryApplyChanges(formatDocument.Project.Solution);
}
}
}
else if (Document.Name.EndsWith(".nf.json"))
{
if (!nfinalextension.JsonModelGenerate)
{
return;
}
project = Document.ProjectItem.ContainingProject;
string parentName = Document.ProjectItem.Name;
string parentFileName = Document.ProjectItem.FileNames[0];
string inputFileContent = null;
using (StreamReader sr = new StreamReader(parentFileName, System.Text.Encoding.UTF8))
{
inputFileContent = sr.ReadToEnd();
}
string nameSpace = GetNameSpace(Document);
string className = parentName.TrimSuffix(".nf.json").Replace('-', '_');
string outPutFileName = parentFileName.TrimSuffix(".nf.json") + ".cs";
ProjectItem projectItem = Helper.ProjectHelpers.FindInProject(outPutFileName);
projectItem?.Document?.Close(vsSaveChanges.vsSaveChangesNo);
if (inputFileContent != null)
{
using (StreamWriter sw = new StreamWriter(outPutFileName, false, System.Text.Encoding.UTF8))
{
Xamasoft.JsonClassGenerator.JsonClassGenerator gen = new Xamasoft.JsonClassGenerator.JsonClassGenerator();
gen.Example = inputFileContent;
gen.InternalVisibility = false;
gen.CodeWriter = new Xamasoft.JsonClassGenerator.CodeWriters.CSharpCodeWriter();
gen.ExplicitDeserialization = false;
gen.Namespace = nameSpace;
gen.NoHelperClass = true;
gen.SecondaryNamespace = nameSpace;
gen.TargetFolder = null;
gen.UseProperties = false;
gen.MainClass = className;
gen.UsePascalCase = false;
gen.UseNestedClasses = false;
gen.ApplyObfuscationAttributes = false;
gen.SingleFile = true;
gen.ExamplesInDocumentation = true;
gen.OutputStream = sw;
gen.GenerateClasses();
OutPutString("生成JSON对应实体类成功:\"" + outPutFileName + "\"");
}
}
if (File.Exists(outPutFileName))
{
Helper.ProjectHelpers.AddNestedFile(Document.ProjectItem, outPutFileName, "Compile", false);
}
}
else if (Document.Name.EndsWith(".nf.sql"))
{
if (!nfinalextension.SqlModelGenerate)
{
return;
}
string parentName = Document.ProjectItem.Name;
string parentFileName = Document.ProjectItem.FileNames[0];
string nameSpace = GetNameSpace(Document);
string fileContent = null;
using (StreamReader sr = new StreamReader(parentFileName, System.Text.Encoding.UTF8))
{
fileContent = sr.ReadToEnd();
}
if (fileContent != null)
{
//复制Sqlite文件,支持Sqlite
if (!Sql.SQLite.CopyFiles.Copy())
{
OutPutString("复制SQLite失败,若想要SQLite实体生成功能正常,请以管理员模式运行!");
}
Sql.SqlDocument sqlDocument = null;
try
{
sqlDocument = new Sql.SqlDocument(parentFileName, nameSpace, fileContent);
}
catch (Exception ex)
{
OutPutString(ex.Message);
}
if (sqlDocument != null)
{
foreach (var model in sqlDocument.modelFileDataList)
{
ProjectItem projectItem = Helper.ProjectHelpers.FindInProject(model.fileName);
projectItem?.Document?.Close(vsSaveChanges.vsSaveChangesNo);
using (StreamWriter sw = new StreamWriter(model.fileName, false, System.Text.Encoding.UTF8))
{
sw.Write(model.content);
sw.Close();
OutPutString("生成sql对应实体类成功:\"" + model.fileName + "\"");
}
if (File.Exists(model.fileName))
{
Helper.ProjectHelpers.AddNestedFile(Document.ProjectItem, model.fileName, "Compile", false);
}
}
}
}
}
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/LucasDot/nfinal2compiler.git
git@gitee.com:LucasDot/nfinal2compiler.git
LucasDot
nfinal2compiler
NFinal2Compiler
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891