Ejemplo n.º 1
0
        /// <summary>
        /// Gather information on all classes, interfaces and structs
        /// Perform code analysis to find scenarios that are erroneous in Windows Runtime</summary>
        public void FindDiagnostics()
        {
            WinRTSyntaxReciever syntaxReciever = (WinRTSyntaxReciever)_context.SyntaxReceiver;

            if (!syntaxReciever.Declarations.Any())
            {
                Report(WinRTRules.NoPublicTypesRule, null);
                return;
            }

            CheckNamespaces();
            CheckDeclarations();
        }
Ejemplo n.º 2
0
        public void Generate()
        {
            if (CatchWinRTDiagnostics())
            {
                Logger.Log("Exiting early -- found errors in authored runtime component.");
                Logger.Close();
                return;
            }

            try
            {
                context.AddSource("System.Runtime.InteropServices.WindowsRuntime", SourceText.From(ArrayAttributes, Encoding.UTF8));
                string          assembly        = context.GetAssemblyName();
                string          version         = context.GetAssemblyVersion();
                MetadataBuilder metadataBuilder = new MetadataBuilder();

                var writer = new WinRTTypeWriter(
                    assembly,
                    version,
                    metadataBuilder,
                    Logger);

                WinRTSyntaxReciever syntaxReciever = (WinRTSyntaxReciever)context.SyntaxReceiver;
                Logger.Log("Found " + syntaxReciever.Declarations.Count + " types");
                foreach (var declaration in syntaxReciever.Declarations)
                {
                    writer.Model = context.Compilation.GetSemanticModel(declaration.SyntaxTree);
                    writer.Visit(declaration);
                }
                writer.FinalizeGeneration();

                GenerateWinMD(metadataBuilder);
                GenerateSources();
            }
            catch (Exception e)
            {
                Logger.Log(e.ToString());
                if (e.InnerException != null)
                {
                    Logger.Log(e.InnerException.ToString());
                }
                Logger.Close();
                throw;
            }

            Logger.Log("Done");
            Logger.Close();
        }
Ejemplo n.º 3
0
        private void CheckNamespaces()
        {
            WinRTSyntaxReciever syntaxReciever = (WinRTSyntaxReciever)_context.SyntaxReceiver;

            // Used to check for conflicitng namespace names
            HashSet <string> namespaceNames = new();

            foreach (var @namespace in syntaxReciever.Namespaces)
            {
                var model           = _context.Compilation.GetSemanticModel(@namespace.SyntaxTree);
                var namespaceSymbol = model.GetDeclaredSymbol(@namespace);

                string namespaceString = namespaceSymbol.ToString();

                bool newNamespaceDeclaration = true;
                // Because modules could have a namespace defined in different places (i.e. defines a partial class)
                // we can't rely on `Contains` so we manually check that namespace names cannot differ by case only
                foreach (var usedNamespaceName in namespaceNames)
                {
                    if (String.Equals(namespaceString, usedNamespaceName, StringComparison.OrdinalIgnoreCase) &&
                        !String.Equals(namespaceString, usedNamespaceName, StringComparison.Ordinal))
                    {
                        newNamespaceDeclaration = false;
                        Report(WinRTRules.NamespacesDifferByCase, namespaceSymbol.Locations.First(), namespaceString);
                    }
                }

                if (newNamespaceDeclaration)
                {
                    namespaceNames.Add(namespaceString);
                }

                if (IsInvalidNamespace(namespaceSymbol, _assemblyName))
                {
                    Report(WinRTRules.DisjointNamespaceRule, namespaceSymbol.Locations.First(), _assemblyName, namespaceString);
                }
            }
        }
Ejemplo n.º 4
0
        private void CheckDeclarations()
        {
            WinRTSyntaxReciever syntaxReciever = (WinRTSyntaxReciever)_context.SyntaxReceiver;

            foreach (var declaration in syntaxReciever.Declarations)
            {
                var model = _context.Compilation.GetSemanticModel(declaration.SyntaxTree);

                // Check symbol information for whether it is public to properly detect partial types
                // which can leave out modifier.
                if (model.GetDeclaredSymbol(declaration).DeclaredAccessibility != Accessibility.Public)
                {
                    continue;
                }

                if (declaration is ClassDeclarationSyntax @class)
                {
                    var classId       = @class.Identifier;
                    var classSymbol   = model.GetDeclaredSymbol(@class);
                    var publicMethods = @class.ChildNodes().OfType <MethodDeclarationSyntax>().Where(IsPublic);
                    var props         = @class.DescendantNodes().OfType <PropertyDeclarationSyntax>().Where(IsPublic);

                    // filter out methods and properties that will be replaced with our custom type mappings
                    IgnoreCustomTypeMappings(classSymbol, ref publicMethods, ref props);

                    if (!classSymbol.IsSealed && !classSymbol.IsStatic)
                    {
                        Report(WinRTRules.UnsealedClassRule, @class.GetLocation(), classId);
                    }

                    OverloadsOperator(@class);
                    HasMultipleConstructorsOfSameArity(@class);

                    if (classSymbol.IsGenericType)
                    {
                        Report(WinRTRules.GenericTypeRule, @class.GetLocation(), classId);
                    }

                    // check for things in nonWindowsRuntimeInterfaces
                    ImplementsInvalidInterface(classSymbol, @class);

                    CheckProperties(props, classId);

                    // check types -- todo: check for !valid types
                    CheckMethods(publicMethods, classId);
                }
                else if (declaration is InterfaceDeclarationSyntax @interface)
                {
                    var interfaceSym = model.GetDeclaredSymbol(@interface);
                    var methods      = @interface.DescendantNodes().OfType <MethodDeclarationSyntax>();
                    var props        = @interface.DescendantNodes().OfType <PropertyDeclarationSyntax>().Where(IsPublic);

                    // filter out methods and properties that will be replaced with our custom type mappings
                    IgnoreCustomTypeMappings(interfaceSym, ref methods, ref props);

                    if (interfaceSym.IsGenericType)
                    {
                        Report(WinRTRules.GenericTypeRule, @interface.GetLocation(), @interface.Identifier);
                    }

                    ImplementsInvalidInterface(interfaceSym, @interface);

                    CheckProperties(props, @interface.Identifier);

                    CheckMethods(methods, @interface.Identifier);
                }
                else if (declaration is StructDeclarationSyntax @struct)
                {
                    CheckStructFields(@struct);
                }
            }
        }