Beispiel #1
0
        public int CompareTo(object obj)
        {
            if (obj == null)
            {
                return(-1);
            }
            var t = obj.GetType();

            if (!typeof(IEntityBaseNode <TEntity>).IsAssignableFrom(t))
            {
                return(-1);
            }
            IEntityBaseNode <TEntity> a = (IEntityBaseNode <TEntity>)obj;

            return(a.Entity.CompareTo(Entity));
        }
        private bool ParseCommand(LinkedListStream <IBaseToken> stream, IBaseNode contentRoot)
        {
            // @NOTE(final): This must always return true, due to the fact that the stream is advanced at least once
            DoxygenToken commandToken = stream.Peek <DoxygenToken>();

            Debug.Assert(commandToken != null && commandToken.Kind == DoxygenTokenKind.Command);

            string commandName = commandToken.Value.Substring(1);

            stream.Next();

            string typeName = "Command";

            var rule = DoxygenSyntax.GetCommandRule(commandName);

            if (rule != null)
            {
                if (rule.Kind == DoxygenSyntax.CommandKind.EndCommandBlock)
                {
                    var t = Top;
                    if (t == null)
                    {
                        AddError(commandToken.Position, $"Unterminated starting command block in command '{commandName}'", typeName, commandName);
                        return(false);
                    }
                    if (t.Entity.Kind != DoxygenEntityKind.BlockCommand)
                    {
                        AddError(commandToken.Position, $"Expect starting command block, but found '{t.Entity.Kind}' in command '{commandName}'", typeName, commandName);
                        return(false);
                    }
                    Pop();
                }

                // Paragraph or section command starts or command block starts -> Close previous paragraph or sectioning command
                if (rule.Kind == DoxygenSyntax.CommandKind.Paragraph ||
                    rule.Kind == DoxygenSyntax.CommandKind.Section ||
                    rule.Kind == DoxygenSyntax.CommandKind.StartCommandBlock)
                {
                    var t = Top;
                    if (t != null)
                    {
                        if (t.Entity.Kind == DoxygenEntityKind.Paragraph ||
                            t.Entity.Kind == DoxygenEntityKind.Section ||
                            t.Entity.Kind == DoxygenEntityKind.SubSection ||
                            t.Entity.Kind == DoxygenEntityKind.SubSubSection)
                        {
                            Pop();
                        }
                    }
                }

                DoxygenEntity commandEntity = null;
                IEntityBaseNode <DoxygenEntity> commandNode = null;
                if (rule.EntityKind != DoxygenEntityKind.None)
                {
                    commandEntity    = new DoxygenEntity(rule.EntityKind, commandToken.Range);
                    commandEntity.Id = commandName;
                    commandNode      = new DoxygenNode(Top, commandEntity);
                    if (rule.IsPush)
                    {
                        Push(commandNode);
                    }
                    else
                    {
                        Add(commandNode);
                    }
                }

                foreach (var arg in rule.Args)
                {
                    DoxygenToken argToken = stream.Peek <DoxygenToken>();
                    if (argToken == null)
                    {
                        break;
                    }
                    DoxygenTokenKind expectedTokenKind = DoxygenSyntax.ArgumentToTokenKindMap.ContainsKey(arg.Kind) ? DoxygenSyntax.ArgumentToTokenKindMap[arg.Kind] : DoxygenTokenKind.Invalid;
                    if (expectedTokenKind == DoxygenTokenKind.Invalid)
                    {
                        break;
                    }
                    if (expectedTokenKind != argToken.Kind)
                    {
                        AddError(argToken.Position, $"Expect argument token '{expectedTokenKind}', but got '{argToken.Kind}'", typeName, commandName);
                        break;
                    }
                    if (commandNode != null)
                    {
                        string paramName  = arg.Name;
                        string paramValue = argToken.Value;
                        commandNode.Entity.AddParameter(argToken, paramName, paramValue);
                    }
                    stream.Next();
                }

                if (commandEntity != null)
                {
                    // Get name and text parameter (Some commands, have different names and text parameters, so there is a variable list of strings)
                    var nameParam = commandEntity.FindParameterByName("name", "id");
                    var textParam = commandEntity.FindParameterByName("text", "title", "caption");
                    if (nameParam == null || string.IsNullOrWhiteSpace(nameParam.Value))
                    {
                        if (rule.Kind == DoxygenSyntax.CommandKind.Section)
                        {
                            if (!"mainpage".Equals(commandName))
                            {
                                AddError(commandToken.Position, $"Missing identifier mapping for command '{commandName}'", typeName, commandName);
                            }
                        }
                    }

                    if (nameParam != null && !string.IsNullOrWhiteSpace(nameParam.Value))
                    {
                        string symbolName = nameParam.Value;
                        Debug.Assert(commandNode != null);
                        if (rule.Kind == DoxygenSyntax.CommandKind.Section)
                        {
                            SourceSymbolKind kind = SourceSymbolKind.DoxygenSection;
                            if ("page".Equals(commandName) || "mainpage".Equals(commandName))
                            {
                                kind = SourceSymbolKind.DoxygenPage;
                            }
                            SymbolCache.AddSource(Tag, symbolName, new SourceSymbol(kind, nameParam.Token.Range, commandNode));
                        }
                        else if ("ref".Equals(commandName) || "refitem".Equals(commandName))
                        {
                            string       referenceValue = nameParam.Value;
                            TextPosition startPos       = new TextPosition(0, nameParam.Token.Position.Line, nameParam.Token.Position.Column);
                            using (TextStream referenceTextStream = new BasicTextStream(referenceValue, startPos, referenceValue.Length))
                            {
                                ReferenceSymbolKind referenceTarget = ReferenceSymbolKind.Any;
                                while (!referenceTextStream.IsEOF)
                                {
                                    char first  = referenceTextStream.Peek();
                                    char second = referenceTextStream.Peek(1);
                                    char third  = referenceTextStream.Peek(2);
                                    if (SyntaxUtils.IsIdentStart(first))
                                    {
                                        referenceTextStream.StartLexeme();
                                        while (!referenceTextStream.IsEOF)
                                        {
                                            if (!SyntaxUtils.IsIdentPart(referenceTextStream.Peek()))
                                            {
                                                break;
                                            }
                                            referenceTextStream.AdvanceColumn();
                                        }
                                        var    refRange          = referenceTextStream.LexemeRange;
                                        string singleRereference = referenceTextStream.GetSourceText(refRange.Index, refRange.Length);
                                        if (referenceTextStream.Peek() == '(')
                                        {
                                            referenceTarget = ReferenceSymbolKind.CppFunction;
                                            referenceTextStream.AdvanceColumn();
                                            while (!referenceTextStream.IsEOF)
                                            {
                                                if (referenceTextStream.Peek() == ')')
                                                {
                                                    break;
                                                }
                                                referenceTextStream.AdvanceColumn();
                                            }
                                        }
                                        var symbolRange = new TextRange(new TextPosition(nameParam.Token.Position.Index + refRange.Position.Index, refRange.Position.Line, refRange.Position.Column), refRange.Length);
                                        SymbolCache.AddReference(Tag, singleRereference, new ReferenceSymbol(referenceTarget, symbolRange, commandNode));
                                    }
                                    else if (first == '#' || first == '.')
                                    {
                                        referenceTarget = ReferenceSymbolKind.CppMember;
                                        referenceTextStream.AdvanceColumn();
                                    }
                                    else if (first == ':' || second == ':')
                                    {
                                        referenceTarget = ReferenceSymbolKind.CppMember;
                                        referenceTextStream.AdvanceColumns(2);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        else if ("subpage".Equals(commandName))
                        {
                            SymbolCache.AddReference(Tag, symbolName, new ReferenceSymbol(ReferenceSymbolKind.DoxygenPage, nameParam.Token.Range, commandNode));
                        }
                    }
                }
                ParseBlockContent(stream, commandNode);
            }
            else
            {
                AddError(commandToken.Position, $"No parse rule for command '{commandName}' found", "Command", commandName);
            }
            return(true);
        }
Beispiel #3
0
 protected void Push(IEntityBaseNode <TEntity> node)
 {
     Add(node);
     _stack.Push(node);
 }