public ReferenceChecker(CodeGenConfig config)
        {
            mCodeGenConfig = config;

            mWorkspace = MSBuildWorkspace.Create();
            mWorkspace.LoadMetadataForReferencedProjects = true;
            mWorkspace.SkipUnrecognizedProjects          = true;

            mProject = mWorkspace.OpenProjectAsync(mCodeGenConfig.Project).Result;

            if (mProject == null)
            {
                throw new ReferenceCheckerException("打开工程文件出错");
            }

            mCompilation = mProject.GetCompilationAsync().Result as CSharpCompilation;

            if (mCompilation == null)
            {
                throw new ReferenceCheckerException("GetCompilationAsync failed");
            }

            mReferenceStrArray = File.ReadAllLines(mCodeGenConfig.Cs2LuaReferenceFilePath);

            for (int i = 0; i < mReferenceStrArray.Length; i++)
            {
                if (mReferenceStrArray[i].StartsWith("CS."))
                {
                    mReferenceStrArray[i] = mReferenceStrArray[i].Replace("CS.", string.Empty);
                }
            }

            mLuaCallCSharpSymbol = mCompilation.GetTypeByMetadataName("XLua.LuaCallCSharpAttribute");

            if (mLuaCallCSharpSymbol == null)
            {
                throw new ReferenceCheckerException("无法获取LuaCallCSharp符号,请确认工程已经导入xlua");
            }
        }
        public CodeGenImpl(CodeGenConfig config)
        {
            mCodeGenConfig = config;

            if (!File.Exists(mCodeGenConfig.Project))
            {
                throw new CodeGenException("Solution文件不存在");
            }

            mWorkspace = MSBuildWorkspace.Create(new Dictionary <string, string> {
                { "CheckForSystemRuntimeDependency", "true" }
            });
            mWorkspace.LoadMetadataForReferencedProjects = true;
            mWorkspace.SkipUnrecognizedProjects          = true;

            mProject = mWorkspace.OpenProjectAsync(mCodeGenConfig.Project).Result;

            if (mProject == null)
            {
                throw new CodeGenException("打开工程文件出错");
            }
            else
            {
                Console.WriteLine("工程名:{0}", mProject.Name);
            }

            if (config.IsResolveReferenceManually)
            {
                Console.WriteLine("By手动解析引用");
                mReferenceResolver = new ResolveReferenceByManual();
            }
            else
            {
                Console.WriteLine("ByRosyln自动解析");
                mReferenceResolver = new ResolveReferenceByRosyln(mProject);
            }

            mCompilation = mReferenceResolver.GetReferenceResolvedCompilation(config);

            if (mCompilation == null)
            {
                throw new CodeGenException("GetCompilationAsync failed");
            }

            if (mCompilation.GetDiagnostics().Where((a) => a.Severity == DiagnosticSeverity.Error).Any())
            {
                var diagnostis = mCompilation.GetDiagnostics().Where((a) => a.Severity == DiagnosticSeverity.Error).ToArray();

                foreach (var item in diagnostis)
                {
                    Console.WriteLine(item.ToString());
                }

                throw new CodeGenException("存在编译错误");
            }

            mLuaTableTypeSymbol = mCompilation.GetTypeByMetadataName("XLua.LuaTable");

            if (mLuaTableTypeSymbol == null)
            {
                throw new CodeGenException("mLuaTableTypeSymbol empty");
            }

            mSystemExceptionTypeSymbol = mCompilation.GetTypeByMetadataName("System.Exception");

            if (mSystemExceptionTypeSymbol == null)
            {
                throw new CodeGenException("mSystemExceptionTypeSymbol empty");
            }

            mLuaFunctionTypeSymbol = mCompilation.GetTypeByMetadataName("XLua.LuaFunction");

            if (mLuaFunctionTypeSymbol == null)
            {
                throw new CodeGenException("mLuaFunctionTypeSymbol empty");
            }

            mXLuaClassProxyAdapterTypeSymbol = mCompilation.GetTypeByMetadataName("XLuaClassProxyAdapter");
            if (mXLuaClassProxyAdapterTypeSymbol == null)
            {
                throw new CodeGenException("mXLuaClassProxyAdapterTypeSymbol empty");
            }
        }
 CSharpCompilation IResolveReference.GetReferenceResolvedCompilation(CodeGenConfig config)
 {
     return(mProject.GetCompilationAsync().Result as CSharpCompilation);
 }
Exemple #4
0
        CSharpCompilation IResolveReference.GetReferenceResolvedCompilation(CodeGenConfig config)
        {
            string path         = Path.GetDirectoryName(config.Project);
            string projFilePath = config.Project;
            string name         = Path.GetFileNameWithoutExtension(projFilePath);

            string systemDllPath = config.SystemDllPath;

            List <string> preprocessors = new List <string>();

            preprocessors.Add("__LUA__");

            //存储引用refs
            List <MetadataReference> refs = new List <MetadataReference>();

            List <string> files = new List <string>();
            Dictionary <string, string> refByNames = new Dictionary <string, string>();
            Dictionary <string, string> refByPaths = new Dictionary <string, string>();

            //从csproj文件中解析XML获取引用
            if (projFilePath.EndsWith(".csproj"))
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(projFilePath);

                //查找ItemGroup下的Reference节点
                var nodes = SelectNodes(xmlDoc, "ItemGroup", "Reference");
                foreach (XmlElement node in nodes)
                {
                    var aliasesNode = SelectSingleNode(node, "Aliases");
                    var pathNode    = SelectSingleNode(node, "HintPath");
                    if (null != pathNode && !refByPaths.ContainsKey(pathNode.InnerText))
                    {
                        if (null != aliasesNode)
                        {
                            refByPaths.Add(pathNode.InnerText, aliasesNode.InnerText);
                        }
                        else
                        {
                            refByPaths.Add(pathNode.InnerText, "global");
                        }
                    }
                    else
                    {
                        string val = node.GetAttribute("Include");
                        if (!string.IsNullOrEmpty(val) && !refByNames.ContainsKey(val))
                        {
                            if (null != aliasesNode)
                            {
                                refByNames.Add(val, aliasesNode.InnerText);
                            }
                            else
                            {
                                refByNames.Add(val, "global");
                            }
                        }
                    }
                }

                string prjOutputDir = "bin/Debug/";
                nodes = SelectNodes(xmlDoc, "PropertyGroup");
                foreach (XmlElement node in nodes)
                {
                    string condition = node.GetAttribute("Condition");
                    var    defNode   = SelectSingleNode(node, "DefineConstants");
                    var    pathNode  = SelectSingleNode(node, "OutputPath");
                    if (null != defNode && null != pathNode)
                    {
                        string text = defNode.InnerText.Trim();
                        if (condition.IndexOf("Debug") > 0 || condition.IndexOf("Release") < 0 && (text == "DEBUG" || text.IndexOf(";DEBUG;") > 0 || text.StartsWith("DEBUG;") || text.EndsWith(";DEBUG")))
                        {
                            preprocessors.AddRange(text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
                            prjOutputDir = pathNode.InnerText.Trim();
                            break;
                        }
                    }
                }

                //查找ItemGroup下的ProjectReference节点
                nodes = SelectNodes(xmlDoc, "ItemGroup", "ProjectReference");
                foreach (XmlElement node in nodes)
                {
                    string val      = node.GetAttribute("Include");
                    string prjFile  = Path.Combine(path, val.Trim());
                    var    nameNode = SelectSingleNode(node, "Name");
                    if (null != prjFile && null != nameNode)
                    {
                        string prjName       = nameNode.InnerText.Trim();
                        string prjOutputFile = ParseProjectOutputFile(prjFile, prjName);
                        string fileName      = Path.Combine(prjOutputDir, prjOutputFile);
                        if (!refByPaths.ContainsKey(fileName))
                        {
                            refByPaths.Add(fileName, "global");
                        }
                    }
                }
                nodes = SelectNodes(xmlDoc, "ItemGroup", "Compile");
                foreach (XmlElement node in nodes)
                {
                    string val = node.GetAttribute("Include");
                    if (!string.IsNullOrEmpty(val) && val.EndsWith(".cs") && !files.Contains(val))
                    {
                        files.Add(val);
                    }
                }

                //确保常用的Assembly被引用
                if (!refByNames.ContainsKey("mscorlib"))
                {
                    refByNames.Add("mscorlib", "global");
                }
                if (!refByNames.ContainsKey("System"))
                {
                    refByNames.Add("System", "global");
                }
                if (!refByNames.ContainsKey("System.Core"))
                {
                    refByNames.Add("System.Core", "global");
                }

                if (string.IsNullOrEmpty(systemDllPath))//默认
                {
                    //用反射添加具体的类名引用
                    foreach (var pair in refByNames)
                    {
#pragma warning disable 618
                        Assembly assembly = Assembly.LoadWithPartialName(pair.Key);
#pragma warning restore 618
                        if (null != assembly)
                        {
                            var arr = System.Collections.Immutable.ImmutableArray.Create(pair.Value);
                            Console.WriteLine(pair.Key);
                            refs.Add(MetadataReference.CreateFromFile(assembly.Location, new MetadataReferenceProperties(MetadataImageKind.Assembly, arr)));
                        }
                    }
                }
                //需配置SystemDLLPath
                else
                {
                    foreach (var pair in refByNames)
                    {
                        string file = Path.Combine(systemDllPath, pair.Key) + ".dll";
                        var    arr  = System.Collections.Immutable.ImmutableArray.Create(pair.Value);
                        refs.Add(MetadataReference.CreateFromFile(file, new MetadataReferenceProperties(MetadataImageKind.Assembly, arr)));
                    }
                }

                //从文件路径添加DLL引用
                foreach (var pair in refByPaths)
                {
                    string fullPath = Path.Combine(path, pair.Key);
                    var    arr      = System.Collections.Immutable.ImmutableArray.Create(pair.Value);
                    Console.WriteLine(fullPath);


                    if (!File.Exists(fullPath))
                    {
                        Console.WriteLine(fullPath + "is not exsit!");
                        continue;
                    }

                    refs.Add(MetadataReference.CreateFromFile(fullPath, new MetadataReferenceProperties(MetadataImageKind.Assembly, arr)));
                }

                //手动构造Complation对象
                CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
                compilationOptions = compilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);
                CSharpCompilation compilation = CSharpCompilation.Create(name);
                compilation = compilation.WithOptions(compilationOptions);

                //手动添加Reference
                compilation = compilation.AddReferences(refs.ToArray());

                //手动添加SyntaxTree
                foreach (string itemFile in files)
                {
                    string filePath = Path.Combine(path, itemFile);
                    string fileName = Path.GetFileNameWithoutExtension(filePath);

                    if (!File.Exists(filePath))
                    {
                        Console.WriteLine(filePath + "is not exsit!");
                        continue;
                    }

                    CSharpParseOptions options = new CSharpParseOptions();
                    options = options.WithPreprocessorSymbols(preprocessors);
                    options = options.WithFeatures(new Dictionary <string, string> {
                        { "IOperation", "true" }
                    });
                    SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(filePath), options, filePath);
                    compilation = compilation.AddSyntaxTrees(tree);
                }
                return(compilation);
            }
            return(null);
        }