示例#1
0
                public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
                {
                    node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node);
                    var attributes = node.AttributeLists.ToString();

                    if (attributes.Contains("[DllImport("))
                    {
                        if (attributes.Contains("[DllImport(\"\""))
                        {
                            return(null);
                        }

                        var methodName = node.Identifier.ValueText;
                        if (this.parent.namesToNamespaces.TryGetValue(methodName, out var requiredNamespace))
                        {
                            var currentNamespace = SyntaxUtils.GetEnclosingNamespace(node);
                            if (requiredNamespace != currentNamespace)
                            {
                                if (!this.namespaceToMovedData.TryGetValue(requiredNamespace, out var movedData))
                                {
                                    movedData = new MovedData();
                                    this.namespaceToMovedData[requiredNamespace] = movedData;
                                }

                                movedData.Methods.Add(node);
                                return(null);
                            }
                        }
                    }

                    return(node);
                }
示例#2
0
        private void AddNode(Architecture arch, SyntaxNode node)
        {
            string name          = SyntaxUtils.GetFullName(node, true);
            string fullSignature = GetFullSignature(node);

            if (!this.namesToInfos.TryGetValue(name, out var crossArchInfos))
            {
                crossArchInfos          = new List <CrossArchInfo>();
                this.namesToInfos[name] = crossArchInfos;
            }

            foreach (var info in crossArchInfos)
            {
                if (info.FullSignature == fullSignature)
                {
                    info.Arch |= arch;
                    return;
                }
            }

            var newInfo = new CrossArchInfo()
            {
                Arch = arch, FullSignature = fullSignature
            };

            crossArchInfos.Add(newInfo);
        }
示例#3
0
 public override void VisitStructDeclaration(StructDeclarationSyntax node)
 {
     if (!SyntaxUtils.IsEmptyStruct(node))
     {
         this.foundStructs.Add(node.Identifier.ValueText);
     }
 }
示例#4
0
            public override SyntaxNode VisitParameter(ParameterSyntax node)
            {
                string fullName = SyntaxUtils.GetFullName(node);

                if (this.GetRemapInfo(fullName, out List <AttributeSyntax> listAttributes, node.Type.ToString(), out string newType, out string newName))
                {
                    node = (ParameterSyntax)base.VisitParameter(node);
                    if (listAttributes != null)
                    {
                        foreach (var attrNode in listAttributes)
                        {
                            var attrListNode =
                                SyntaxFactory.AttributeList(
                                    SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode));
                            node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode));
                        }
                    }

                    if (newName != null)
                    {
                        node = node.WithIdentifier(SyntaxFactory.Identifier(newName));
                    }

                    if (newType != null)
                    {
                        node = node.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space));

                        // Get rid of the NativeTypeName attribute so the type we just changed to doesn't get overridden
                        var attr = SyntaxUtils.GetAttribute(node.AttributeLists, "NativeTypeName");
                        if (attr != null)
                        {
                            node = node.RemoveNode(attr, SyntaxRemoveOptions.KeepLeadingTrivia);
                        }
                    }
                }
示例#5
0
 public void SkipAllWhitespaces()
 {
     do
     {
         char c0 = Peek();
         char c1 = Peek(1);
         if (c0 == InvalidCharacter)
         {
             break;
         }
         else if (c0 == '\t')
         {
             AdvanceTab();
         }
         else if (SyntaxUtils.IsLineBreak(c0))
         {
             int nb = SyntaxUtils.GetLineBreakChars(c0, c1);
             AdvanceLine(nb);
         }
         else if (char.IsWhiteSpace(c0))
         {
             AdvanceColumn();
         }
         else
         {
             break;
         }
     } while (!IsEOF);
 }
示例#6
0
        public int AdvanceAuto(int numChars = 1)
        {
            // @NOTE(final): This is super slow, so only use it when needed
            Debug.Assert(numChars >= 1);
            TextPosition p      = TextPosition;
            int          result = 0;

            while (result < numChars)
            {
                char c0 = Peek();
                char c1 = Peek(1);
                if (SyntaxUtils.IsLineBreak(c0))
                {
                    int lb = SyntaxUtils.GetLineBreakChars(c0, c1);
                    p.Line++;
                    p.Column = 1;
                    p.Index += lb;
                    result  += lb;
                }
                if (c0 == '\t')
                {
                    p.Column += ColumnsPerTab;
                    p.Index++;
                    result++;
                }
                else
                {
                    p.Column++;
                    p.Index++;
                    result++;
                }
            }
            TextPosition = p;
            return(result);
        }
示例#7
0
        public void ShouldDocument(string uncommentedCode, string expectedCommentedCode)
        {
            // Arrange
            var options = new CtorDocumentationOptions
            {
                Enabled  = true,
                Required = true,
                Summary  = new SummaryDocumentationOptions
                {
                    Template = "Creates a new instance of the {name} class."
                },
                Parameters = new ParamsDocumentationOptions
                {
                    Enabled  = true,
                    Template = "The {name}."
                },
                Exceptions = new ExceptionDocumentationOptions
                {
                    Enabled = true
                }
            };

            var ctorDeclarationSyntax = SyntaxUtils.Parse <ConstructorDeclarationSyntax>(uncommentedCode);

            var strategy = new ConstructorDocumentationStrategy(NullLogger <ConstructorDocumentationStrategy> .Instance,
                                                                new HumanizeFormatter(new DocumentationOptions()),
                                                                options);

            // Act
            var documentedSyntax = strategy.Apply(ctorDeclarationSyntax);

            // Assert
            documentedSyntax.ToFullString().Trim().ShouldBe(expectedCommentedCode.Trim());
        }
示例#8
0
        public void Setup()
        {
            _classDocumentationStrategy = new ClassDocumentationStrategy(
                NullLogger <ClassDocumentationStrategy> .Instance,
                new HumanizeFormatter(new DocumentationOptions()),
                new ClassDocumentationOptions());

            _classDeclarationSyntax = SyntaxUtils.Parse <ClassDeclarationSyntax>(ClassWithInheritance);
        }
示例#9
0
            public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node)
            {
                // If the struct is empty and we found a non-empty struct in all the source files, delete it
                if (SyntaxUtils.IsEmptyStruct(node) && this.nonEmptyStructs.Contains(node.Identifier.ValueText))
                {
                    return(null);
                }

                return(base.VisitStructDeclaration(node));
            }
        public static bool IsPotentialCrossArch(MethodDeclarationSyntax node)
        {
            var dllImportAttr = SyntaxUtils.GetAttribute(node.AttributeLists, "DllImport");

            if (dllImportAttr != null)
            {
                return(true);
            }

            return(false);
        }
        private static string GetNativeTypeForSignature(SyntaxList <AttributeListSyntax> attributeLists)
        {
            var nativeType = SyntaxUtils.GetNativeTypeNameFromAttributesLists(attributeLists);

            // If the native type has a '/' it means it contains a path, which won't compare well
            // in a cloud build when different architectures are built on different agents. Just
            // return null in that case
            if (nativeType != null && nativeType.Contains('/'))
            {
                nativeType = null;
            }

            return(nativeType);
        }
        public void ShouldDocument(string uncommentedCode, string expectedCommentedCode)
        {
            // Arrange
            var classDeclarationSyntax = SyntaxUtils.Parse <ClassDeclarationSyntax>(uncommentedCode);

            var strategy = new ClassDocumentationStrategy(NullLogger <ClassDocumentationStrategy> .Instance,
                                                          new HumanizeFormatter(new DocumentationOptions()),
                                                          new ClassDocumentationOptions());

            // Act
            var documentedSyntax = strategy.Apply(classDeclarationSyntax);

            // Assert
            documentedSyntax.ToFullString().ShouldBe(expectedCommentedCode);
        }
示例#13
0
 public void AdvanceManual(char first, char second)
 {
     if (first == '\t')
     {
         AdvanceTab();
     }
     else if (SyntaxUtils.IsLineBreak(first))
     {
         int nb = SyntaxUtils.GetLineBreakChars(first, second);
         AdvanceLine(nb);
     }
     else
     {
         AdvanceColumn();
     }
 }
示例#14
0
            public override SyntaxNode VisitParameter(ParameterSyntax node)
            {
                string fullName = GetFullNameWithoutArchSuffix(node);

                if (this.GetRemapInfo(fullName, out List <AttributeSyntax> listAttributes, node.Type.ToString(), out string newType, out string newName))
                {
                    node = (ParameterSyntax)base.VisitParameter(node);
                    if (listAttributes != null)
                    {
                        foreach (var attrNode in listAttributes)
                        {
                            var attrListNode =
                                SyntaxFactory.AttributeList(
                                    SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode));
                            node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode));
                        }
                    }

                    if (newName != null)
                    {
                        node = node.WithIdentifier(SyntaxFactory.Identifier(newName));
                    }

                    if (newType != null)
                    {
                        node = node.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space));

                        // Get rid of the NativeTypeName attribute so the type we just changed to doesn't get overridden
                        var attr = SyntaxUtils.GetAttribute(node.AttributeLists, "NativeTypeName");
                        if (attr != null)
                        {
                            var attrList = (AttributeListSyntax)attr.Parent;

                            // We want to delete the attribute, but if it's the last one in the list,
                            // remove the list
                            if (attrList.Attributes.Count == 1)
                            {
                                node = node.RemoveNode(attrList, SyntaxRemoveOptions.KeepLeadingTrivia);
                            }
                            // If it's not the last attribute, just remove the attribute
                            else
                            {
                                node = node.RemoveNode(attr, SyntaxRemoveOptions.KeepLeadingTrivia);
                            }
                        }
                    }
                }
示例#15
0
        private bool LexUntilCodeEnd(CommandResult commandResult)
        {
            // Special case, we dont want to parse doxygen stuff inside a code section
            // so we wait until a @endcode follows
            bool isComplete = false;

            while (!Buffer.IsEOF)
            {
                char c0 = Buffer.Peek();
                char c1 = Buffer.Peek(1);
                if ((c0 == '@' || c0 == '\\') && SyntaxUtils.IsIdentStart(c1))
                {
                    Buffer.StartLexeme();
                    Buffer.AdvanceColumn();
                    Buffer.AdvanceColumnsWhile(SyntaxUtils.IsIdentPart);
                    string ident = Buffer.GetSourceText(Buffer.LexemeStart.Index + 1, Buffer.LexemeWidth - 1);
                    if ("endcode".Equals(ident))
                    {
                        PushToken(DoxygenTokenPool.Make(DoxygenTokenKind.CommandEnd, Buffer.LexemeRange, true));
                        isComplete = true;
                        break;
                    }
                }
                else if (SyntaxUtils.IsLineBreak(c0))
                {
                    int lb = SyntaxUtils.GetLineBreakChars(c0, c1);
                    Buffer.AdvanceLine(lb);
                }
                else if ('\t'.Equals(c0))
                {
                    Buffer.AdvanceTab();
                }
                else
                {
                    Buffer.AdvanceColumn();
                }
            }
            if (!isComplete)
            {
                AddError(commandResult.StartPos, $"Unterminated code-block, expect '@endcode' or '\\endcode'", "Code", commandResult.CommandName);
                return(false);
            }
            return(true);
        }
        private void AddNode(Architecture arch, SyntaxNode node)
        {
            string name          = SyntaxUtils.GetFullName(node, true);
            string fullSignature = GetFullSignature(node);
            string altSignature  = string.Empty;

            if (arch == Architecture.X86 && node is StructDeclarationSyntax structNode)
            {
                var packing4AttrList =
                    SyntaxFactory.AttributeList(
                        SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(
                            SyntaxFactory.Attribute(
                                SyntaxFactory.ParseName("StructLayout"),
                                SyntaxFactory.ParseAttributeArgumentList("(LayoutKind.Sequential, Pack = 4)"))));

                var tempNode = structNode.AddAttributeLists(packing4AttrList);
                altSignature = GetFullSignature(tempNode);
            }

            lock (this.namesToInfos)
            {
                if (!this.namesToInfos.TryGetValue(name, out var crossArchInfos))
                {
                    crossArchInfos          = new List <CrossArchInfo>();
                    this.namesToInfos[name] = crossArchInfos;
                }

                foreach (var info in crossArchInfos)
                {
                    if (info.FullSignature == fullSignature || info.FullSignature == altSignature)
                    {
                        info.Arch |= arch;
                        return;
                    }
                }

                var newInfo = new CrossArchInfo()
                {
                    Arch = arch, FullSignature = fullSignature
                };
                crossArchInfos.Add(newInfo);
            }
        }
示例#17
0
            public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node)
            {
                string fullName = SyntaxUtils.GetFullName(node);

                // Remove duplicate delegates in this tree
                if (this.visitedDelegateNames.Contains(fullName))
                {
                    return(null);
                }

                this.visitedDelegateNames.Add(fullName);

                string returnFullName = $"{fullName}::return";

                if (this.GetRemapInfo(returnFullName, out List <AttributeSyntax> listAttributes, node.ReturnType.ToString(), out var newType, out _))
                {
                    node = (DelegateDeclarationSyntax)base.VisitDelegateDeclaration(node);
                    if (listAttributes != null)
                    {
                        foreach (var attrNode in listAttributes)
                        {
                            var attrListNode =
                                SyntaxFactory.AttributeList(
                                    SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode))
                                .WithTarget(
                                    SyntaxFactory.AttributeTargetSpecifier(
                                        SyntaxFactory.Token(SyntaxKind.ReturnKeyword)));

                            node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode));
                        }

                        if (newType != null)
                        {
                            node = node.WithReturnType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space));
                        }
                    }

                    return(node);
                }

                return(base.VisitDelegateDeclaration(node));
            }
示例#18
0
                private SyntaxNode VisitDeclarationSyntax(MemberDeclarationSyntax node, string name)
                {
                    if (this.parent.namesToNamespaces.TryGetValue(name, out var requiredNamespace))
                    {
                        var currentNamespace = SyntaxUtils.GetEnclosingNamespace(node);
                        if (requiredNamespace != currentNamespace)
                        {
                            if (!this.namespaceToMovedData.TryGetValue(requiredNamespace, out var movedData))
                            {
                                movedData = new MovedData();
                                this.namespaceToMovedData[requiredNamespace] = movedData;
                            }

                            movedData.Others.Add(node);
                            return(null);
                        }
                    }

                    return(node);
                }
示例#19
0
        private LexResult LexIdent(bool isPreprocessor)
        {
            Debug.Assert(SyntaxUtils.IsIdentStart(Buffer.Peek()));
            StringBuilder identBuffer = new StringBuilder();

            while (!Buffer.IsEOF)
            {
                char c = Buffer.Peek();
                if (SyntaxUtils.IsIdentPart(c))
                {
                    identBuffer.Append(c);
                    Buffer.AdvanceColumn();
                }
                else
                {
                    break;
                }
            }
            CppTokenKind kind        = CppTokenKind.IdentLiteral;
            TextPosition identStart  = Buffer.LexemeStart;
            int          identLength = Buffer.LexemeWidth;
            string       identString = identBuffer.ToString();

            if (isPreprocessor && PreProcessorKeywords.Contains(identString))
            {
                kind = CppTokenKind.PreprocessorKeyword;
            }
            else if (ReservedKeywords.Contains(identString))
            {
                kind = CppTokenKind.ReservedKeyword;
            }
            else if (TypeKeywords.Contains(identString) || GlobalClassKeywords.Contains(identString))
            {
                kind = CppTokenKind.TypeKeyword;
            }
            else
            {
                kind = CppTokenKind.IdentLiteral;
            }
            return(new LexResult(kind, true));
        }
示例#20
0
            public override SyntaxNode VisitParameter(ParameterSyntax node)
            {
                string fullName = SyntaxUtils.GetFullName(node);

                if (this.GetRemapInfo(fullName, out List <AttributeSyntax> listAttributes, node.Type.ToString(), out string newType, out string newName))
                {
                    node = (ParameterSyntax)base.VisitParameter(node);
                    if (listAttributes != null)
                    {
                        foreach (var attrNode in listAttributes)
                        {
                            var attrListNode =
                                SyntaxFactory.AttributeList(
                                    SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode));
                            node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode));
                        }
                    }

                    if (newName != null)
                    {
                        node = node.WithIdentifier(SyntaxFactory.Identifier(newName));
                    }

                    if (newType != null)
                    {
                        node = node.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space));
                    }

                    return(node);
                }

                var ret = (ParameterSyntax)base.VisitParameter(node);

                // Get rid of default parameter values
                if (ret.Default != null)
                {
                    ret = ret.WithDefault(null);
                }

                return(ret);
            }
示例#21
0
 public void SkipLineBreaks(SkipType type)
 {
     do
     {
         char c0 = Peek();
         char c1 = Peek(1);
         if (c0 == InvalidCharacter)
         {
             break;
         }
         else if (SyntaxUtils.IsLineBreak(c0))
         {
             int lb = SyntaxUtils.GetLineBreakChars(c0, c1);
             AdvanceLine(lb);
         }
         else
         {
             break;
         }
     } while (!IsEOF && type == SkipType.All);
 }
示例#22
0
        public static LexResult LexSingleLineComment(TextStream stream, bool init)
        {
            CppTokenKind kind = CppTokenKind.SingleLineComment;

            if (init)
            {
                Debug.Assert(stream.Peek(0) == '/');
                Debug.Assert(stream.Peek(1) == '/');
                stream.AdvanceColumns(2);
                if (DoxygenSyntax.SingleLineDocChars.Contains(stream.Peek()))
                {
                    stream.AdvanceColumn();
                    kind = CppTokenKind.SingleLineCommentDoc;
                }
            }
            while (!stream.IsEOF)
            {
                char c0 = stream.Peek();
                char c1 = stream.Peek(1);
                if (c0 == TextStream.InvalidCharacter)
                {
                    break;
                }
                else if (SyntaxUtils.IsLineBreak(c0))
                {
                    break;
                }
                else if (c0 == '\t')
                {
                    stream.AdvanceTab();
                }
                else
                {
                    stream.AdvanceColumn();
                }
            }
            bool isComplete = stream.IsEOF || SyntaxUtils.IsLineBreak(stream.Peek());

            return(new LexResult(kind, isComplete));
        }
            private static SyntaxList <AttributeListSyntax> FixRemappedAttributes(
                SyntaxList <AttributeListSyntax> existingAttrList,
                List <AttributeSyntax> remappedListAttributes,
                AttributeTargetSpecifierSyntax target)
            {
                if (remappedListAttributes == null)
                {
                    return(existingAttrList);
                }

                foreach (var attrNode in remappedListAttributes)
                {
                    var attrName = attrNode.Name.ToString();
                    if (attrName.EndsWith(EncodeHelpers.AttributeToRemoveSuffix))
                    {
                        var attrNameToRemove = attrName.Substring(0, attrName.Length - EncodeHelpers.AttributeToRemoveSuffix.Length);

                        existingAttrList = SyntaxUtils.RemoveAttribute(existingAttrList, attrNameToRemove);
                    }
                    else
                    {
                        // Remove any existing attribute with the same name
                        existingAttrList = SyntaxUtils.RemoveAttribute(existingAttrList, attrName);

                        var attrListNode =
                            SyntaxFactory.AttributeList(
                                SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode));
                        if (target != null)
                        {
                            attrListNode = attrListNode.WithTarget(target);
                        }

                        existingAttrList = existingAttrList.Add(attrListNode);
                    }
                }

                return(existingAttrList);
            }
示例#24
0
 public void SkipSpacings(SkipType type)
 {
     do
     {
         char c = Peek();
         if (c == InvalidCharacter)
         {
             break;
         }
         else if (c == '\t')
         {
             AdvanceTab();
         }
         else if (SyntaxUtils.IsSpacing(c))
         {
             AdvanceColumn();
         }
         else
         {
             break;
         }
     } while (!IsEOF && type == SkipType.All);
 }
示例#25
0
 private string GetFullNameWithArch(SyntaxNode node, Architecture arch)
 {
     return(GetUniqueNameWithArches(SyntaxUtils.GetFullName(node, true), arch));
 }
示例#26
0
        private CommandResult LexCommandTokens()
        {
            Debug.Assert(DoxygenSyntax.IsCommandBegin(Buffer.Peek()));

            // Command
            Buffer.StartLexeme();
            Buffer.AdvanceColumn();

            DoxygenTokenKind kind = DoxygenTokenKind.Command;
            {
                char first = Buffer.Peek();
                switch (first)
                {
                case '{':
                case '}':
                    kind = (first == '{') ? DoxygenTokenKind.GroupStart : DoxygenTokenKind.GroupEnd;
                    Buffer.AdvanceColumn();
                    break;

                case '$':
                case '@':
                case '\\':
                case '~':
                case '<':
                case '=':
                case '>':
                case '#':
                case '"':
                    Buffer.AdvanceColumn();
                    break;

                case ':':
                case '|':
                case '-':
                    Buffer.AdvanceColumnsWhile(d => d.Equals(first));
                    break;

                default:
                    if (DoxygenSyntax.IsCommandIdentStart(first))
                    {
                        while (!Buffer.IsEOF)
                        {
                            if (!DoxygenSyntax.IsCommandIdentPart(Buffer.Peek()))
                            {
                                break;
                            }
                            Buffer.AdvanceColumn();
                        }
                    }
                    break;
                }
            }

            TextPosition commandStart = Buffer.LexemeStart;
            int          commandLen   = Buffer.LexemeWidth;
            string       commandName  = Buffer.GetSourceText(Buffer.LexemeStart.Index + 1, commandLen - 1);
            var          rule         = DoxygenSyntax.GetCommandRule(commandName);

            if (rule != null)
            {
                if (rule.Kind == DoxygenSyntax.CommandKind.StartCommandBlock)
                {
                    kind = DoxygenTokenKind.CommandStart;
                }
                else if (rule.Kind == DoxygenSyntax.CommandKind.EndCommandBlock)
                {
                    kind = DoxygenTokenKind.CommandEnd;
                }
            }
            else
            {
                // @NOTE(final): Group start/end are not a "known" command
                if (kind != DoxygenTokenKind.GroupStart && kind != DoxygenTokenKind.GroupEnd)
                {
                    kind = DoxygenTokenKind.InvalidCommand;
                }
            }
            DoxygenToken commandToken = DoxygenTokenPool.Make(kind, Buffer.LexemeRange, true);

            PushToken(commandToken);

            CommandResult result = new CommandResult(commandStart, rule, commandName);

            string typeName = "Command";

            if (rule != null)
            {
                int  argNumber  = 0;
                int  argCount   = rule.Args.Count();
                bool noMoreArgs = false;
                foreach (var arg in rule.Args)
                {
                    // @TODO(final): Handle rule repeat type for arguments on same type
                    char first = Buffer.Peek();
                    if (!arg.Flags.HasFlag(DoxygenSyntax.ArgumentFlags.DirectlyAfterCommand))
                    {
                        if (SyntaxUtils.IsSpacing(first) || first == '\t')
                        {
                            Buffer.SkipSpacings(TextStream.SkipType.All);
                        }
                        else
                        {
                            // No more arguments are following
                            noMoreArgs = true;
                        }
                    }

                    Buffer.StartLexeme();

                    // Prefix
                    string prefix    = arg.Prefix;
                    string postfix   = arg.Postfix;
                    bool   hadPrefix = false;
                    if (prefix != null && !noMoreArgs)
                    {
                        if (!string.IsNullOrEmpty(prefix))
                        {
                            if (Buffer.CompareText(0, prefix) == 0)
                            {
                                Buffer.AdvanceColumns(prefix.Length);
                                hadPrefix = true;
                            }
                        }
                        else if ((prefix.Length == 0) && (!string.IsNullOrEmpty(postfix)))
                        {
                            hadPrefix = true;
                        }
                    }

                    switch (arg.Kind)
                    {
                    case DoxygenSyntax.ArgumentKind.PrefixToPostfix:
                    {
                        if (hadPrefix && !noMoreArgs)
                        {
                            Debug.Assert(!string.IsNullOrEmpty(postfix));
                            bool foundPrefixToPostfix = false;
                            while (!Buffer.IsEOF)
                            {
                                if (Buffer.CompareText(0, postfix) == 0)
                                {
                                    Buffer.AdvanceColumns(postfix.Length);
                                    foundPrefixToPostfix = true;
                                    break;
                                }
                                else if (SyntaxUtils.IsLineBreak(Buffer.Peek()))
                                {
                                    break;
                                }
                                else
                                {
                                    Buffer.AdvanceColumn();
                                }
                            }
                            if (arg.IsOptional || foundPrefixToPostfix)
                            {
                                DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentCaption, Buffer.LexemeRange, foundPrefixToPostfix);
                                PushToken(argToken);
                            }
                            else if (arg.IsRequired)
                            {
                                AddError(Buffer.TextPosition, $"Expected postfix '{postfix}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                return(result);
                            }
                        }
                        else if (arg.IsOptional)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentCaption, Buffer.LexemeRange, false);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Expected prefix '{prefix}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.MultipleObjectReference:
                    case DoxygenSyntax.ArgumentKind.SingleObjectReference:
                    {
                        // @TODO(final): ReferencedObject is not always a identifier
                        // Here are some examples of valid referenced objects:
                        // simple_identifier
                        // a_function()
                        // my::awesome::namespace::object
                        // my::awesome::namespace::function()
                        // my#awesome#namespace#function()
                        // method1,method2(),class#field
                        bool foundRef = false;
                        if (!noMoreArgs)
                        {
                            bool allowMultiple  = arg.Kind == DoxygenSyntax.ArgumentKind.MultipleObjectReference;
                            bool requireIdent   = true;
                            int  referenceCount = 0;
                            while (!Buffer.IsEOF)
                            {
                                int  oldPos = Buffer.StreamPosition;
                                char c0     = Buffer.Peek();
                                char c1     = Buffer.Peek(1);
                                if (!requireIdent)
                                {
                                    if (c0 == ':' && c1 == ':')
                                    {
                                        Buffer.AdvanceColumns(2);
                                        requireIdent = true;
                                        continue;
                                    }
                                    else if (c0 == '#')
                                    {
                                        Buffer.AdvanceColumn();
                                        requireIdent = true;
                                        continue;
                                    }
                                    else if (c0 == ',' && referenceCount > 0 && allowMultiple)
                                    {
                                        Buffer.AdvanceColumn();
                                        requireIdent = true;
                                        continue;
                                    }
                                    else
                                    {
                                        // Correct termination of object-reference
                                        foundRef = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    if (SyntaxUtils.IsIdentStart(c0))
                                    {
                                        requireIdent = false;
                                        while (!Buffer.IsEOF)
                                        {
                                            if (!SyntaxUtils.IsIdentPart(Buffer.Peek()))
                                            {
                                                break;
                                            }
                                            Buffer.AdvanceColumn();
                                        }
                                        if (Buffer.Peek() == '(')
                                        {
                                            // Parse until right parent
                                            Buffer.AdvanceColumn();
                                            bool terminatedFunc = false;
                                            while (!Buffer.IsEOF)
                                            {
                                                if (Buffer.Peek() == ')')
                                                {
                                                    Buffer.AdvanceColumn();
                                                    terminatedFunc = true;
                                                    break;
                                                }
                                                Buffer.AdvanceAuto();
                                            }
                                            if (!terminatedFunc)
                                            {
                                                AddError(Buffer.TextPosition, $"Unterminated function reference for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                                return(result);
                                            }
                                        }
                                        ++referenceCount;
                                        continue;
                                    }
                                    else
                                    {
                                        AddError(Buffer.TextPosition, $"Requires identifier, but found '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                        return(result);
                                    }
                                }
                            }
                            if (Buffer.IsEOF)
                            {
                                // Correct termination of object-reference when stream ends (Single-line)
                                foundRef = true;
                            }
                        }
                        if (arg.IsOptional || foundRef)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentIdent, Buffer.LexemeRange, foundRef);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.Identifier:
                    {
                        bool foundIdent = false;

                        // Special handling for @param command and ... parameter
                        if (!noMoreArgs && "param".Equals(commandName) && (arg.Kind == DoxygenSyntax.ArgumentKind.Identifier))
                        {
                            if (Buffer.Peek() == '.')
                            {
                                char c1 = Buffer.Peek(1);
                                char c2 = Buffer.Peek(2);
                                if (c1 == '.' && c2 == '.')
                                {
                                    Buffer.AdvanceColumns(3);
                                    foundIdent = true;
                                }
                            }
                        }

                        // We dont allow parsing a ident, when any special handling was matched
                        if (!noMoreArgs && !foundIdent && SyntaxUtils.IsIdentStart(Buffer.Peek()))
                        {
                            foundIdent = true;
                            while (!Buffer.IsEOF)
                            {
                                if (!SyntaxUtils.IsIdentPart(Buffer.Peek()))
                                {
                                    break;
                                }
                                Buffer.AdvanceColumn();
                            }
                        }
                        if (arg.IsOptional || foundIdent)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentIdent, Buffer.LexemeRange, foundIdent);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.HeaderFile:
                    case DoxygenSyntax.ArgumentKind.HeaderName:
                    {
                        bool foundFilename = false;
                        if (!noMoreArgs)
                        {
                            bool requiredQuotes = arg.Kind == DoxygenSyntax.ArgumentKind.HeaderName;
                            char curChar        = Buffer.Peek();
                            if (curChar == '<' || curChar == '\"')
                            {
                                char quoteChar = curChar == '<' ? '>' : '\"';
                                Buffer.AdvanceColumn();
                                while (!Buffer.IsEOF)
                                {
                                    curChar = Buffer.Peek();
                                    if (curChar == quoteChar)
                                    {
                                        Buffer.AdvanceColumn();
                                        foundFilename = true;
                                        break;
                                    }
                                    else if (SyntaxUtils.IsLineBreak(curChar))
                                    {
                                        break;
                                    }
                                    Buffer.AdvanceColumn();
                                }
                                if (!foundFilename)
                                {
                                    AddError(Buffer.TextPosition, $"Unterminated filename, expect quote char '{quoteChar}' but got '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                    return(result);
                                }
                            }
                            else if (!requiredQuotes)
                            {
                                if (SyntaxUtils.IsFilename(Buffer.Peek()))
                                {
                                    foundFilename = true;
                                    while (!Buffer.IsEOF)
                                    {
                                        if (!SyntaxUtils.IsFilename(Buffer.Peek()))
                                        {
                                            break;
                                        }
                                        Buffer.AdvanceColumn();
                                    }
                                }
                            }
                        }
                        if (arg.IsOptional || foundFilename)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentFile, Buffer.LexemeRange, foundFilename);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.SingleWord:
                    {
                        // @TODO(final): IsWordStart()
                        bool foundWord = false;
                        if (!noMoreArgs && char.IsLetterOrDigit(Buffer.Peek()))
                        {
                            foundWord = true;
                            while (!Buffer.IsEOF)
                            {
                                // @TODO(final): IsWordPart()
                                if (char.IsWhiteSpace(Buffer.Peek()))
                                {
                                    break;
                                }
                                Buffer.AdvanceColumn();
                            }
                        }
                        if (arg.IsOptional || foundWord)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentCaption, Buffer.LexemeRange, foundWord);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.QuotedString:
                    {
                        bool isComplete = false;

                        // @TODO(final): Make quotes configurable in the argument rule
                        bool hasQuote = Buffer.Peek() == '"' || Buffer.Peek() == '<';
                        char endQuote = char.MaxValue;
                        if (hasQuote && !noMoreArgs)
                        {
                            endQuote = Buffer.Peek() == '<' ? '>' : '"';
                            Buffer.AdvanceColumn();
                            while (!Buffer.IsEOF)
                            {
                                if (!hasQuote)
                                {
                                    if (char.IsWhiteSpace(Buffer.Peek()))
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    if (Buffer.Peek() == endQuote)
                                    {
                                        Buffer.AdvanceColumn();
                                        isComplete = true;
                                        break;
                                    }
                                    else if (SyntaxUtils.IsLineBreak(Buffer.Peek()) || Buffer.Peek() == TextStream.InvalidCharacter)
                                    {
                                        break;
                                    }
                                }
                                Buffer.AdvanceColumn();
                            }
                            if (!isComplete)
                            {
                                AddError(Buffer.TextPosition, $"Unterminated quote string for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                                return(result);
                            }
                        }
                        if (arg.IsOptional || isComplete)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentText, Buffer.LexemeRange, isComplete);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unexpected character '{Buffer.Peek()}' for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.UntilEndOfLine:
                    {
                        bool eolFound = false;
                        if (!noMoreArgs)
                        {
                            while (!Buffer.IsEOF)
                            {
                                if (SyntaxUtils.IsLineBreak(Buffer.Peek()))
                                {
                                    eolFound = true;
                                    break;
                                }
                                Buffer.AdvanceColumn();
                            }
                            if (Buffer.IsEOF)
                            {
                                eolFound = true;
                            }
                        }
                        if (arg.IsOptional || eolFound)
                        {
                            DoxygenToken argToken = DoxygenTokenPool.Make(DoxygenTokenKind.ArgumentText, Buffer.LexemeRange, true);
                            PushToken(argToken);
                        }
                        else if (arg.IsRequired)
                        {
                            AddError(Buffer.TextPosition, $"Unterminated end-of-line for argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    break;

                    case DoxygenSyntax.ArgumentKind.ComplexLine:
                    case DoxygenSyntax.ArgumentKind.ComplexBlock:
                        // @TODO(final): Implement complex line/block properly
                        goto CommandDone;

                    default:
                        AddError(Buffer.TextPosition, $"Unsupported argument ({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                        return(result);
                    }

                    // Postfix
                    if (!noMoreArgs && (hadPrefix && !string.IsNullOrWhiteSpace(postfix) && arg.Kind != DoxygenSyntax.ArgumentKind.PrefixToPostfix))
                    {
                        if (Buffer.CompareText(0, postfix) == 0)
                        {
                            Buffer.AdvanceColumns(prefix.Length);
                        }
                        else
                        {
                            AddError(Buffer.TextPosition, $"Expected postfix '{postfix}' for pp-argument({argNumber}:{arg}) in command '{commandName}'", typeName, commandName);
                            return(result);
                        }
                    }
                    ++argNumber;
                }
            }

CommandDone:
            result.IsValid = true;

            return(result);
        }
        public IEnumerable <Architecture> GetSignatureArchGroupings(SyntaxNode node)
        {
            string name = SyntaxUtils.GetFullName(node, true);

            return(this.GetSignatureArchGroupings(name));
        }
 public static bool IsPotentialCrossArch(StructDeclarationSyntax node)
 {
     return(node.Parent is NamespaceDeclarationSyntax && !SyntaxUtils.IsEmptyStruct(node));
 }
示例#29
0
            public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node)
            {
                string fullName = SyntaxUtils.GetFullName(node);

                this.GetRemapInfo(fullName, out var listAttributes, node.Declaration.Type.ToString(), out string newType, out string newName);

                // ClangSharp mistakenly emits string[] for WCHAR[] Foo = "Bar".
                // Change it to string
                if (newType == null && node.Declaration.Type.ToString() == "string[]")
                {
                    newType = "string";
                }

                // Turn public static readonly Guids into string constants with an attribute
                // to signal language projections to turn them into Guid constants. Guid constants
                // aren't allowed in metadata, requiring us to surface them this way
                if (node.Modifiers.ToString() == "public static readonly" && node.Declaration.Type.ToString() == "Guid")
                {
                    Guid guidVal        = Guid.Empty;
                    var  varInitializer = node.Declaration.Variables.First().Initializer;
                    if (varInitializer.Value is ObjectCreationExpressionSyntax objCreationSyntax)
                    {
                        var args = objCreationSyntax.ArgumentList.Arguments;
                        if (args.Count == 11)
                        {
                            uint   p0  = EncodeHelpers.ParseHex(args[0].ToString());
                            ushort p1  = (ushort)EncodeHelpers.ParseHex(args[1].ToString());
                            ushort p2  = (ushort)EncodeHelpers.ParseHex(args[2].ToString());
                            byte   p3  = (byte)EncodeHelpers.ParseHex(args[3].ToString());
                            byte   p4  = (byte)EncodeHelpers.ParseHex(args[4].ToString());
                            byte   p5  = (byte)EncodeHelpers.ParseHex(args[5].ToString());
                            byte   p6  = (byte)EncodeHelpers.ParseHex(args[6].ToString());
                            byte   p7  = (byte)EncodeHelpers.ParseHex(args[7].ToString());
                            byte   p8  = (byte)EncodeHelpers.ParseHex(args[8].ToString());
                            byte   p9  = (byte)EncodeHelpers.ParseHex(args[9].ToString());
                            byte   p10 = (byte)EncodeHelpers.ParseHex(args[10].ToString());

                            guidVal = new Guid(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
                        }
                        else if (objCreationSyntax.ArgumentList.Arguments.Count == 1)
                        {
                            // If this is an invalid format, remove the node
                            if (!Guid.TryParse(objCreationSyntax.ArgumentList.Arguments[0].ToString(), out guidVal))
                            {
                                return(null);
                            }
                        }
                    }

                    if (guidVal == Guid.Empty)
                    {
                        return(node);
                    }

                    node = node.RemoveNode(varInitializer, SyntaxRemoveOptions.KeepExteriorTrivia | SyntaxRemoveOptions.KeepEndOfLine);
                    node = node.AddAttributeLists(EncodeHelpers.ConvertGuidToAttributeList(guidVal).WithLeadingTrivia(node.GetLeadingTrivia()));

                    return(node);
                }

                node = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node);
                if (listAttributes != null)
                {
                    foreach (var attrNode in listAttributes)
                    {
                        var attrListNode =
                            SyntaxFactory.AttributeList(
                                SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode));
                        node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode));
                    }
                }

                var firstVar = node.Declaration.Variables.First();

                if (newName != null)
                {
                    var newVar = SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(newName));
                    node = node.ReplaceNode(firstVar, newVar);
                }

                if (newType != null)
                {
                    node = node.WithDeclaration(node.Declaration.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space)));
                }

                return(node);
            }
示例#30
0
            public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
            {
                // Skip methods where we weren't given a import lib name. Should we warn the caller?
                if (node.AttributeLists.ToString().Contains("[DllImport(\"\""))
                {
                    return(null);
                }

                string fullName = SyntaxUtils.GetFullName(node);

                // Remove duplicate static methods
                if (node.Body == null)
                {
                    // If this function is supposed to be in a certain namespace, remove it if it's not.
                    // We only respect this for static methods
                    if (this.requiredNamespaces.TryGetValue(fullName, out var requiredNamespace))
                    {
                        var ns = GetEnclosingNamespace(node);
                        if (ns != requiredNamespace)
                        {
                            return(null);
                        }
                    }

                    // Remove duplicate methods in this tree
                    if (this.visitedStaticMethodNames.Contains(fullName))
                    {
                        return(null);
                    }

                    this.visitedStaticMethodNames.Add(fullName);
                }
                // Any method with a body has to be part of a call to a vtable for an interface.
                // If it's not, get rid of it
                else if (!node.Body.ToString().Contains("GetDelegateForFunctionPointer"))
                {
                    return(null);
                }

                string returnFullName = $"{fullName}::return";

                // Find remap info for the return parameter for this method and apply any that we find
                if (this.GetRemapInfo(returnFullName, out List <AttributeSyntax> listAttributes, node.ReturnType.ToString(), out var newType, out _))
                {
                    node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node);
                    if (listAttributes != null)
                    {
                        foreach (var attrNode in listAttributes)
                        {
                            var attrListNode =
                                SyntaxFactory.AttributeList(
                                    SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode))
                                .WithTarget(
                                    SyntaxFactory.AttributeTargetSpecifier(
                                        SyntaxFactory.Token(SyntaxKind.ReturnKeyword)));

                            node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode));
                        }
                    }

                    if (newType != null)
                    {
                        node = node.WithReturnType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space));
                    }

                    return(node);
                }

                return(base.VisitMethodDeclaration(node));
            }