示例#1
0
        public TranslationUnit WriteToEmpty(string source)
        {
            var translationUnit = Index.ParseTranslationUnit(
                TestFiles.Empty,
                new[] { "-std=c++11" },
                new[] { new UnsavedFile(TestFiles.Empty, source) },
                TranslationUnitCreationOptions.DetailedPreprocessingRecord);
            var set = DiagnosticSet.FromTranslationUnit(translationUnit);

            if (set.GetNumDiagnostics() != 0)
            {
                Assert.Fail(set.GetDiagnostic(0).ToString());
            }
            return(translationUnit);
        }
示例#2
0
        public void GetOneDiagnosticInTranslationUnit()
        {
            string source = "#endif";

            using (var empty = disposables.Index.ParseTranslationUnit(
                       TestFiles.Empty,
                       null,
                       new[] { new UnsavedFile(TestFiles.Empty, source) },
                       TranslationUnitCreationOptions.DetailedPreprocessingRecord))
            {
                var set = DiagnosticSet.FromTranslationUnit(empty);
                Assert.AreEqual <uint>(1, set.GetNumDiagnostics());
                Assert.IsNotNull(set.GetDiagnostic(0));
                Assert.IsNull(set.GetDiagnostic(1));

                var diagnostic = set.GetDiagnostic(0);
                Assert.IsNull(diagnostic.GetChildDiagnostics());
                Assert.AreEqual(DiagnosticSeverity.Error, diagnostic.GetSeverity());
            }
        }
        public void GenerateTypes(string libraryName = "imobiledevice")
        {
            string[] arguments =
            {
                // Use the C++ backend
                "-x",
                "c++",

                // Parse the doxygen comments
                "-Wdocumentation",

                // Target 32-bit OS
                "-m32"
            };

            arguments = arguments.Concat(this.IncludeDirectories.Select(x => "-I" + x)).ToArray();

            FunctionVisitor functionVisitor;

            using (var createIndex = new Index(false, true))
                using (var translationUnit = createIndex.ParseTranslationUnit(this.InputFile, arguments))
                {
                    StringWriter errorWriter    = new StringWriter();
                    var          set            = DiagnosticSet.FromTranslationUnit(translationUnit);
                    var          numDiagnostics = set.GetNumDiagnostics();

                    bool hasError   = false;
                    bool hasWarning = false;

                    for (uint i = 0; i < numDiagnostics; ++i)
                    {
                        Diagnostic diagnostic = set.GetDiagnostic(i);
                        var        severity   = diagnostic.GetSeverity();

                        switch (severity)
                        {
                        case DiagnosticSeverity.Error:
                        case DiagnosticSeverity.Fatal:
                            hasError = true;
                            break;

                        case DiagnosticSeverity.Warning:
                            hasWarning = true;
                            break;
                        }

                        var location = diagnostic.GetLocation();
                        var fileName = location.SourceFile;
                        var line     = location.Line;

                        var message = diagnostic.GetSpelling();
                        errorWriter.WriteLine($"{severity}: {fileName}:{line} {message}");
                    }

                    if (hasError)
                    {
                        throw new Exception(errorWriter.ToString());
                    }

                    if (hasWarning)
                    {
                        // Dump the warnings to the console output.
                        Console.WriteLine(errorWriter.ToString());
                    }

                    // Generate the marhaler types for string arrays (char **)
                    var arrayMarshalerGenerator = new ArrayMarshalerGenerator(this);
                    arrayMarshalerGenerator.Generate();

                    // Creates enums
                    var enumVisitor     = new EnumVisitor(this);
                    var realEnumVisitor = new DelegatingCursorVisitor(enumVisitor.Visit);
                    var cursor          = translationUnit.GetCursor();
                    realEnumVisitor.VisitChildren(cursor);

                    // Creates structs
                    var structVisitor     = new StructVisitor(this);
                    var realStructVisitor = new DelegatingCursorVisitor(structVisitor.Visit);
                    realStructVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates safe handles & delegates
                    var typeDefVisitor     = new TypeDefVisitor(this);
                    var realTypeDefVisitor = new DelegatingCursorVisitor(typeDefVisitor.Visit);
                    realTypeDefVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates functions in a NativeMethods class
                    functionVisitor = new FunctionVisitor(this, libraryName);
                    var realFunctionVisitor = new DelegatingCursorVisitor(functionVisitor.Visit);
                    realFunctionVisitor.VisitChildren(translationUnit.GetCursor());

                    createIndex.Dispose();
                }

            // Update the SafeHandle to call the _free method
            var handles = this.Types.Where(t => t.Name.EndsWith("Handle"));

            foreach (var handle in handles)
            {
                var freeMethod = functionVisitor.NativeMethods.Members
                                 .OfType <CodeMemberMethod>()
                                 .Where(m =>
                                        (m.Name.EndsWith("_free") || m.Name.EndsWith("_disconnect")) &&
                                        m.Parameters.Count == 1 &&
                                        m.Parameters[0].Type.BaseType == handle.Name)
                                 .SingleOrDefault();

                if (freeMethod == null)
                {
                    continue;
                }

                var type = (HandleType)((NustacheGeneratedType)handle).Type;
                type.ReleaseMethodName         = freeMethod.Name;
                type.ReleaseMethodReturnsValue = freeMethod.ReturnType.BaseType != "System.Void";

                // Directly pass the IntPtr, becuase the handle itself will already be in the 'closed' state
                // when this method is called.
                freeMethod.Parameters[0].Type      = new CodeTypeReference(typeof(IntPtr));
                freeMethod.Parameters[0].Direction = FieldDirection.In;
            }

            // Extract the API interface and class, as well as the Exception class. Used for DI.
            ApiExtractor extractor = new ApiExtractor(this, functionVisitor);

            extractor.Generate();

            // Add the 'Error' extension IsError and ThrowOnError extension methods
            var extensionsExtractor = new ErrorExtensionExtractor(this, functionVisitor);

            extensionsExtractor.Generate();

            // Patch the native methods to be compatible with .NET Core - basically,
            // do the marshalling ourselves
            NativeMethodOverloadGenerator.Generate(this);
        }
示例#4
0
        private static int ProcessArgs(ParseResult result)
        {
            result.ShowHelpOrErrorIfAppropriate();

            var command       = result.AppliedCommand();
            var globalOptions = result["dotnet-migrate-2017"];

            ProgramBase.ApplyVerbosity(result, globalOptions);

            Log.Verbose(result.Diagram());

            var items = command.Value <string[]>();

            var conversionOptions = new ConversionOptions
            {
                ProjectCache = new DefaultProjectCache(),
                ForceOnUnsupportedProjects = command.ValueOrDefault <bool>("force"),
                KeepAssemblyInfo           = command.ValueOrDefault <bool>("keep-assembly-info")
            };

            switch (command.Name)
            {
            case "evaluate":
            case "migrate":
                var frameworks = command.ValueOrDefault <string[]>("target-frameworks");
                if (frameworks != null)
                {
                    conversionOptions.TargetFrameworks = frameworks;
                }
                break;
            }

            var logic = new CommandLogic();

            switch (command.Name)
            {
            case "wizard":
                var diagnostics = new DiagnosticSet(Vs15DiagnosticSet.All);
                diagnostics.ExceptWith(DiagnosticSet.All);
                var sets = new WizardTransformationSets
                {
                    MigrateSet = new ChainTransformationSet(
                        new BasicSimplifyTransformationSet(Vs15TransformationSet.TargetVisualStudioVersion),
                        Vs15TransformationSet.TrueInstance),
                    ModernCleanUpSet = new BasicSimplifyTransformationSet(
                        Vs15TransformationSet.TargetVisualStudioVersion),
                    ModernizeSet = new ChainTransformationSet(
                        new BasicSimplifyTransformationSet(Vs15TransformationSet.TargetVisualStudioVersion),
                        Vs15ModernizationTransformationSet.TrueInstance),
                    Diagnostics = diagnostics
                };

                logic.ExecuteWizard(items, conversionOptions, sets);
                break;

            case "evaluate":
                logic.ExecuteEvaluate(items, conversionOptions, Vs15TransformationSet.Instance, new AnalysisOptions(Vs15DiagnosticSet.All));
                break;

            case "analyze":
                logic.ExecuteAnalyze(items, conversionOptions, new AnalysisOptions(Vs15DiagnosticSet.All));
                break;

            case "migrate":
                conversionOptions.AppendTargetFrameworkToOutputPath = !command.ValueOrDefault <bool>("old-output-path");

                var forceTransformations = command.ValueOrDefault <string[]>("force-transformations");
                if (forceTransformations != null)
                {
                    conversionOptions.ForceDefaultTransforms = forceTransformations;
                }

                logic.ExecuteMigrate(items, command.ValueOrDefault <bool>("no-backup"), conversionOptions, Vs15TransformationSet.Instance);
                break;
            }

            return(result.Execute().Code);
        }
示例#5
0
        public void GenerateTypes()
        {
            string[] arguments =
            {
                // Use the C++ backend
                "-x",
                "c++",

                // Parse the doxygen comments
                "-Wdocumentation",
            };

            arguments = arguments.Concat(this.IncludeDirectories.Select(x => "-I" + x)).ToArray();

            using (var createIndex = new Index(false, true))
                using (var translationUnit = createIndex.ParseTranslationUnit(this.InputFile, arguments))
                {
                    StringWriter errorWriter    = new StringWriter();
                    var          set            = DiagnosticSet.FromTranslationUnit(translationUnit);
                    var          numDiagnostics = set.GetNumDiagnostics();

                    bool hasError   = false;
                    bool hasWarning = false;

                    for (uint i = 0; i < numDiagnostics; ++i)
                    {
                        Diagnostic diagnostic = set.GetDiagnostic(i);
                        var        severity   = diagnostic.GetSeverity();

                        switch (severity)
                        {
                        case DiagnosticSeverity.Error:
                        case DiagnosticSeverity.Fatal:
                            hasError = true;
                            break;

                        case DiagnosticSeverity.Warning:
                            hasWarning = true;
                            break;
                        }

                        var location = diagnostic.GetLocation();
                        var fileName = location.SourceFile;
                        var line     = location.Line;

                        var message = diagnostic.GetSpelling();
                        errorWriter.WriteLine($"{severity}: {fileName}:{line} {message}");
                    }

                    if (hasError)
                    {
                        throw new Exception(errorWriter.ToString());
                    }

                    if (hasWarning)
                    {
                        // Dump the warnings to the console output.
                        Console.WriteLine(errorWriter.ToString());
                    }

                    // Creates enums
                    var enumVisitor     = new EnumVisitor(this);
                    var realEnumVisitor = new DelegatingCursorVisitor(enumVisitor.Visit);
                    realEnumVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates handles
                    var typeDefVisitor     = new TypeDefVisitor(this);
                    var realTypeDefVisitor = new DelegatingCursorVisitor(typeDefVisitor.Visit);
                    realTypeDefVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates C# methods for C functions
                    var functionVisitor     = new FunctionVisitor(this);
                    var realFunctionVisitor = new DelegatingCursorVisitor(functionVisitor.Visit);
                    realFunctionVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates C# strucs for C structs
                    var structVisitor     = new StructVisitor(this);
                    var realStructVisitor = new DelegatingCursorVisitor(structVisitor.Visit);
                    realStructVisitor.VisitChildren(translationUnit.GetCursor());
                }
        }
示例#6
0
        public void Generate(string targetDirectory, string libraryName = "imobiledevice")
        {
            string[] arguments =
            {
                // Use the C++ backend
                "-x",
                "c++",

                // Parse the doxygen comments
                "-Wdocumentation",

                // Target 32-bit OS
                "-m32"
            };

            arguments = arguments.Concat(this.IncludeDirectories.Select(x => "-I" + x)).ToArray();

            FunctionVisitor functionVisitor;

            using (var createIndex = new Index(false, true))
                using (var translationUnit = createIndex.ParseTranslationUnit(this.InputFile, arguments))
                {
                    StringWriter errorWriter    = new StringWriter();
                    var          set            = DiagnosticSet.FromTranslationUnit(translationUnit);
                    var          numDiagnostics = set.GetNumDiagnostics();

                    bool hasError   = false;
                    bool hasWarning = false;

                    for (uint i = 0; i < numDiagnostics; ++i)
                    {
                        Diagnostic diagnostic = set.GetDiagnostic(i);
                        var        severity   = diagnostic.GetSeverity();

                        switch (severity)
                        {
                        case DiagnosticSeverity.Error:
                        case DiagnosticSeverity.Fatal:
                            hasError = true;
                            break;

                        case DiagnosticSeverity.Warning:
                            hasWarning = true;
                            break;
                        }

                        var location = diagnostic.GetLocation();
                        var fileName = location.SourceFile;
                        var line     = location.Line;

                        var message = diagnostic.GetSpelling();
                        errorWriter.WriteLine($"{severity}: {fileName}:{line} {message}");
                    }

                    if (hasError)
                    {
                        throw new Exception(errorWriter.ToString());
                    }

                    if (hasWarning)
                    {
                        // Dump the warnings to the console output.
                        Console.WriteLine(errorWriter.ToString());
                    }

                    // Generate the marhaler types for string arrays (char **)
                    var arrayMarshalerGenerator = new ArrayMarshalerGenerator(this);
                    arrayMarshalerGenerator.Generate();

                    // Creates enums
                    var enumVisitor     = new EnumVisitor(this);
                    var realEnumVisitor = new DelegatingCursorVisitor(enumVisitor.Visit);
                    var cursor          = translationUnit.GetCursor();
                    realEnumVisitor.VisitChildren(cursor);

                    // Creates structs
                    var structVisitor     = new StructVisitor(this);
                    var realStructVisitor = new DelegatingCursorVisitor(structVisitor.Visit);
                    realStructVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates safe handles & delegates
                    var typeDefVisitor     = new TypeDefVisitor(this);
                    var realTypeDefVisitor = new DelegatingCursorVisitor(typeDefVisitor.Visit);
                    realTypeDefVisitor.VisitChildren(translationUnit.GetCursor());

                    // Creates functions in a NativeMethods class
                    functionVisitor = new FunctionVisitor(this, libraryName);
                    var realFunctionVisitor = new DelegatingCursorVisitor(functionVisitor.Visit);
                    realFunctionVisitor.VisitChildren(translationUnit.GetCursor());

                    createIndex.Dispose();
                }

            var moduleDirectory = Path.Combine(targetDirectory, this.Name);

            if (!Directory.Exists(moduleDirectory))
            {
                Directory.CreateDirectory(moduleDirectory);
            }

            // Update the SafeHandle to call the _free method
            var handles = this.Types.Where(t => t.Name.EndsWith("Handle"));

            foreach (var handle in handles)
            {
                var freeMethod = functionVisitor.NativeMethods.Members
                                 .OfType <CodeMemberMethod>()
                                 .Where(m =>
                                        (m.Name.EndsWith("_free") || m.Name.EndsWith("_disconnect")) &&
                                        m.Parameters.Count == 1 &&
                                        m.Parameters[0].Type.BaseType == handle.Name)
                                 .SingleOrDefault();

                if (freeMethod == null)
                {
                    continue;
                }

                // Directly pass the IntPtr, becuase the handle itself will already be in the 'closed' state
                // when this method is called.
                freeMethod.Parameters[0].Type      = new CodeTypeReference(typeof(IntPtr));
                freeMethod.Parameters[0].Direction = FieldDirection.In;

                var releaseMethod = handle.Members.OfType <CodeMemberMethod>().Single(m => m.Name == "ReleaseHandle");

                // Sample statement:
                //   System.Diagnostics.Debug.WriteLine("Releasing {0} {1}", this.GetType().Name, this.handle);
                //   this.Api.Plist.plist_free(this.handle);
                //   return true;
                releaseMethod.Statements.Clear();

                // Trace the release call:
                // Debug.WriteLine("Releasing {0} {1}", this.GetType().Name, this.handle);
                releaseMethod.Statements.Add(
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeTypeReferenceExpression(typeof(Debug)),
                            "WriteLine"),
                        new CodePrimitiveExpression("Releasing {0} {1} using {2}. This object was created at {3}"),
                        new CodePropertyReferenceExpression(
                            new CodeMethodInvokeExpression(
                                new CodeThisReferenceExpression(),
                                nameof(GetType)),
                            "Name"),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            "handle"),
                        new CodePropertyReferenceExpression(
                            new CodeThisReferenceExpression(),
                            "Api"),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            "creationStackTrace")));

                var freeMethodInvokeExpression =
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodePropertyReferenceExpression(
                                new CodePropertyReferenceExpression(
                                    new CodeThisReferenceExpression(),
                                    "Api"),
                                this.Name),
                            freeMethod.Name),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            "handle"));

                if (freeMethod.ReturnType.BaseType != "System.Void")
                {
                    // If the free method returns a value, it's an error code, and we can make sure the value indicates
                    // success.
                    releaseMethod.Statements.Add(
                        new CodeMethodReturnStatement(
                            new CodeBinaryOperatorExpression(
                                freeMethodInvokeExpression,
                                CodeBinaryOperatorType.IdentityEquality,
                                new CodePropertyReferenceExpression(
                                    new CodeTypeReferenceExpression($"{this.Name}Error"),
                                    "Success"))));
                }
                else
                {
                    // If it does not, we always return true (which is a pitty, but this is how plist is implemented for now)
                    // - on the other hand, in how many ways can free() really fail? :-)
                    releaseMethod.Statements.Add(freeMethodInvokeExpression);
                    releaseMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(true)));
                }
            }

            // Extract the API interface and class, as well as the Exception class. Used for DI.
            ApiExtractor extractor = new ApiExtractor(this, functionVisitor);

            extractor.Generate();

            // Add the 'Error' extension IsError and ThrowOnError extension methods
            var extensionsExtractor = new ErrorExtensionExtractor(this, functionVisitor);

            extensionsExtractor.Generate();

            // Patch the native methods to be compatible with .NET Core - basically,
            // do the marshalling ourselves
            NativeMethodOverloadGenerator.Generate(this);

            // Write the files
            foreach (var declaration in this.Types)
            {
                if (declaration.Name.EndsWith("Private"))
                {
                    continue;
                }

                // Generate the container unit
                CodeCompileUnit program = new CodeCompileUnit();

                // Generate the namespace
                CodeNamespace ns = new CodeNamespace($"iMobileDevice.{this.Name}");
                ns.Imports.Add(new CodeNamespaceImport("System.Runtime.InteropServices"));
                ns.Imports.Add(new CodeNamespaceImport("System.Diagnostics"));
                ns.Imports.Add(new CodeNamespaceImport("iMobileDevice.iDevice"));
                ns.Imports.Add(new CodeNamespaceImport("iMobileDevice.Lockdown"));
                ns.Imports.Add(new CodeNamespaceImport("iMobileDevice.Afc"));
                ns.Imports.Add(new CodeNamespaceImport("iMobileDevice.Plist"));
                ns.Types.Add(declaration);
                program.Namespaces.Add(ns);

                string suffix = string.Empty;
                if (declaration.UserData.Contains("FileNameSuffix"))
                {
                    suffix = (string)declaration.UserData["FileNameSuffix"];
                }

                string path = Path.Combine(moduleDirectory, $"{declaration.Name}{suffix}.cs");

                using (var outFile = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None))
                    using (var fileWriter = new StreamWriter(outFile))
                        using (var indentedTextWriter = new CSharpTextWriter(fileWriter, "    "))
                        {
                            // Generate source code using the code provider.
                            indentedTextWriter.Generate(ns);
                            indentedTextWriter.Flush();
                        }

                // Add #if statements for code that doesn't work on .NET Core
                if (true)
                {
                    string content = File.ReadAllText(path);

                    content = content.Replace("#region !core", "#if !NETSTANDARD1_5");
                    content = content.Replace("#endregion", "#endif");

                    using (StringReader reader = new StringReader(content))
                        using (StreamWriter writer = new StreamWriter(path))
                        {
                            while (reader.Peek() >= 0)
                            {
                                string line = reader.ReadLine();

                                if (line.Contains(nameof(SecurityPermissionAttribute)) ||
                                    line.Contains(nameof(ReliabilityContractAttribute)) ||
                                    line.Contains(nameof(SerializableAttribute)))
                                {
                                    writer.WriteLine("#if !NETSTANDARD1_5");
                                    writer.WriteLine(line);
                                    writer.WriteLine("#endif");
                                }
                                else if (line.Contains("SerializationInfo info"))
                                {
                                    writer.WriteLine("#if !NETSTANDARD1_5");
                                    writer.WriteLine(line);
                                    writer.WriteLine(reader.ReadLine());
                                    writer.WriteLine(reader.ReadLine());
                                    writer.WriteLine(reader.ReadLine());
                                    writer.WriteLine("#endif");
                                }
                                else
                                {
                                    writer.WriteLine(line);
                                }
                            }
                        }
                }

                // Fix other CodeDOM shortcomings
                if (declaration.Name.EndsWith("NativeMethods") && string.IsNullOrEmpty(suffix))
                {
                    string content = File.ReadAllText(path);
                    content = content.Replace("public abstract", "public static extern");
                    File.WriteAllText(path, content);
                }

                if (declaration.Name.EndsWith("Extensions"))
                {
                    string content = File.ReadAllText(path);
                    content = content.Replace("public class", "public static class");
                    File.WriteAllText(path, content);
                }
            }
        }