Beispiel #1
0
        public static List <ParameterInformation> GetInfoParams(bhlParser.FuncDeclContext funcDecl)
        {
            List <ParameterInformation> funcParameters = new List <ParameterInformation>();

            if (funcDecl.funcParams() is bhlParser.FuncParamsContext funcParams)
            {
                var funcParamDeclares = funcParams.funcParamDeclare();
                for (int k = 0; k < funcParamDeclares.Length; k++)
                {
                    var fpd = funcParamDeclares[k];
                    if (fpd.exception != null)
                    {
                        continue;
                    }

                    var fpdl = $"{(fpd.isRef() != null ? "ref " : "")}{fpd.type().NAME().GetText()} {fpd.NAME().GetText()}";
                    if (fpd.assignExp() is bhlParser.AssignExpContext assignExp)
                    {
                        fpdl += assignExp.GetText();
                    }

                    funcParameters.Add(new ParameterInformation
                    {
                        label         = fpdl,
                        documentation = ""
                    });
                }
            }

            return(funcParameters);
        }
Beispiel #2
0
        public override object VisitFuncDecl(bhlParser.FuncDeclContext ctx)
        {
            var funcDeclName = ctx.NAME();
            var retType      = ctx.retType();
            var funcParams   = ctx.funcParams();
            var funcBlock    = ctx.funcBlock();

            if (funcDeclName != null)
            {
                var funcDeclNameText = funcDeclName.GetText();
                if (!funcDecls.ContainsKey(funcDeclNameText))
                {
                    funcDecls.Add(funcDeclNameText, ctx);
                }
            }

            var keywordStopIdx = retType?.Start.StartIndex ?? (funcDeclName?.Symbol.StartIndex ?? 0);

            AddSemanticToken(ctx.Start.StartIndex, Math.Max(ctx.Start.StartIndex, keywordStopIdx - 1),
                             SemanticTokenTypes.keyword);

            if (retType != null)
            {
                foreach (var t in retType.type())
                {
                    if (t.exception != null)
                    {
                        continue;
                    }

                    Visit(t);
                }
            }

            if (funcDeclName != null)
            {
                AddSemanticToken(funcDeclName, SemanticTokenTypes.function,
                                 SemanticTokenModifiers.definition, SemanticTokenModifiers.@static);
            }

            if (funcParams != null)
            {
                foreach (var funcParamDeclare in funcParams.funcParamDeclare())
                {
                    VisitFuncParamDeclare(funcParamDeclare);
                }
            }

            if (funcBlock != null)
            {
                Visit(funcBlock);
            }

            return(null);
        }
Beispiel #3
0
        SignatureInformation GetFuncSignInfo(bhlParser.FuncDeclContext funcDecl)
        {
            SignatureInformation funcSignature = new SignatureInformation();

            string label = funcDecl.NAME().GetText() + "(";

            List <ParameterInformation> funcParameters = BHLSPUtil.GetInfoParams(funcDecl);

            if (funcParameters.Count > 0)
            {
                for (int k = 0; k < funcParameters.Count; k++)
                {
                    var funcParameter = funcParameters[k];
                    label += funcParameter.label.Value;
                    if (k != funcParameters.Count - 1)
                    {
                        label += ", ";
                    }
                }
            }
            else
            {
                label += "<no parameters>";
            }

            label += ")";

            if (funcDecl.retType() is bhlParser.RetTypeContext retType)
            {
                label += ":";

                var types = retType.type();
                for (int n = 0; n < types.Length; n++)
                {
                    var t = types[n];
                    if (t.exception != null)
                    {
                        continue;
                    }

                    label += t.NAME().GetText() + " ";
                }
            }
            else
            {
                label += ":void";
            }

            funcSignature.label      = label;
            funcSignature.parameters = funcParameters.ToArray();
            return(funcSignature);
        }
Beispiel #4
0
        public override RpcResult Hover(TextDocumentPositionParams args)
        {
            BHLSPWorkspace.self.TryAddDocument(args.textDocument.uri);
            if (BHLSPWorkspace.self.FindDocument(args.textDocument.uri) is BHLTextDocument document)
            {
                int line      = (int)args.position.line;
                int character = (int)args.position.character;

                int idx = document.GetIndex(line, character);

                bhlParser.CallExpContext callExp = null;

                foreach (IParseTree node in BHLSPUtil.DFS(document.ToParser().program()))
                {
                    if (node is ParserRuleContext prc)
                    {
                        if (prc.Start.StartIndex <= idx && idx <= prc.Stop.StopIndex)
                        {
                            callExp = prc as bhlParser.CallExpContext;
                            break;
                        }
                    }
                }

                bhlParser.FuncDeclContext funcDecl = null;

                if (callExp != null)
                {
                    string callExpName = callExp.NAME().GetText();

                    foreach (var doc in BHLSPWorkspace.self.ForEachBhlImports(document))
                    {
                        if (doc.FuncDecls.ContainsKey(callExpName))
                        {
                            funcDecl = doc.FuncDecls[callExpName];
                            break;
                        }
                    }
                }

                if (funcDecl != null)
                {
                    string label = funcDecl.NAME().GetText() + "(";

                    List <ParameterInformation> funcParameters = BHLSPUtil.GetInfoParams(funcDecl);

                    if (funcParameters.Count > 0)
                    {
                        for (int k = 0; k < funcParameters.Count; k++)
                        {
                            var funcParameter = funcParameters[k];
                            label += funcParameter.label.Value;
                            if (k != funcParameters.Count - 1)
                            {
                                label += ", ";
                            }
                        }
                    }
                    else
                    {
                        label += "<no parameters>";
                    }

                    label += ")";

                    if (funcDecl.retType() is bhlParser.RetTypeContext retType)
                    {
                        label += ":";

                        var types = retType.type();
                        for (int n = 0; n < types.Length; n++)
                        {
                            var t = types[n];
                            if (t.exception != null)
                            {
                                continue;
                            }

                            label += t.NAME().GetText() + " ";
                        }
                    }
                    else
                    {
                        label += ":void";
                    }

                    return(RpcResult.Success(new Hover
                    {
                        contents = new MarkupContent
                        {
                            kind = "plaintext",
                            value = label
                        }
                    }));
                }
            }

            return(RpcResult.Success());
        }
Beispiel #5
0
        /**
         * The result type LocationLink[] got introduced with version 3.14.0
         * and depends on the corresponding client capability textDocument.definition.linkSupport.
         */
        public override RpcResult GotoDefinition(DefinitionParams args)
        {
            BHLSPWorkspace.self.TryAddDocument(args.textDocument.uri);
            if (BHLSPWorkspace.self.FindDocument(args.textDocument.uri) is BHLTextDocument document)
            {
                int line      = (int)args.position.line;
                int character = (int)args.position.character;

                int idx = document.GetIndex(line, character);

                bhlParser.FuncDeclContext funcDecl            = null;
                BHLTextDocument           funcDeclBhlDocument = null;

                bhlParser.CallExpContext      callExp      = null;
                bhlParser.MemberAccessContext memberAccess = null;
                bhlParser.TypeContext         type         = null;
                bhlParser.StatementContext    statement    = null;

                foreach (IParseTree node in BHLSPUtil.DFS(document.ToParser().program()))
                {
                    if (node is ParserRuleContext prc)
                    {
                        if (prc.Start.StartIndex <= idx && idx <= prc.Stop.StopIndex)
                        {
                            funcDecl     = prc as bhlParser.FuncDeclContext;
                            callExp      = prc as bhlParser.CallExpContext;
                            memberAccess = prc as bhlParser.MemberAccessContext;
                            type         = prc as bhlParser.TypeContext;
                            statement    = prc as bhlParser.StatementContext;
                            break;
                        }
                    }
                }

                if (funcDecl == null)
                {
                    string classTypeName   = string.Empty;
                    string memberClassName = string.Empty;

                    if (type?.NAME() != null)
                    {
                        classTypeName = type.NAME().GetText();
                    }
                    else if (memberAccess != null)
                    {
                        bhlParser.CallExpContext  callExpMemberAccess        = null;
                        bhlParser.FuncDeclContext memberAccessParentFuncDecl = null;

                        memberClassName = memberAccess.NAME().GetText();

                        for (RuleContext parent = memberAccess.Parent; parent != null; parent = parent.Parent)
                        {
                            if (callExpMemberAccess == null && parent is bhlParser.CallExpContext)
                            {
                                callExpMemberAccess = parent as bhlParser.CallExpContext;
                            }

                            if (parent is bhlParser.FuncDeclContext)
                            {
                                memberAccessParentFuncDecl = parent as bhlParser.FuncDeclContext;
                                break;
                            }
                        }

                        if (callExpMemberAccess != null)
                        {
                            string callExpMemberAccessName = callExpMemberAccess.NAME().GetText();

                            if (memberAccessParentFuncDecl?.NAME() != null)
                            {
                                foreach (IParseTree node in BHLSPUtil.DFS(memberAccessParentFuncDecl))
                                {
                                    if (node is bhlParser.FuncParamDeclareContext funcParamDeclare)
                                    {
                                        bhlParser.TypeContext funcParamDeclareType = funcParamDeclare.type();
                                        if (funcParamDeclareType.funcType() != null || funcParamDeclareType.ARR() != null)
                                        {
                                            continue;
                                        }

                                        if (funcParamDeclare.NAME()?.GetText() == callExpMemberAccessName)
                                        {
                                            classTypeName = funcParamDeclareType.GetText();
                                            break;
                                        }
                                    }

                                    if (node is bhlParser.VarDeclareContext varDeclare && varDeclare?.NAME().GetText() == callExpMemberAccessName)
                                    {
                                        classTypeName = varDeclare.type().NAME().GetText();
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(classTypeName))
                    {
                        bhlParser.ClassDeclContext classDecl            = null;
                        BHLTextDocument            classDeclBhlDocument = null;

                        foreach (var doc in BHLSPWorkspace.self.ForEachBhlImports(document))
                        {
                            if (doc.ClassDecls.ContainsKey(classTypeName))
                            {
                                classDecl            = doc.ClassDecls[classTypeName];
                                classDeclBhlDocument = doc;
                                break;
                            }
                        }

                        if (classDecl != null)
                        {
                            bhlParser.ClassMemberContext classMember = null;

                            if (!string.IsNullOrEmpty(memberClassName))
                            {
                                foreach (var classMemberContext in classDecl.classBlock().classMembers().classMember())
                                {
                                    if (classMemberContext.funcDecl()?.NAME()?.GetText() != null)
                                    {
                                        if (classMemberContext.funcDecl().NAME().GetText() == memberClassName)
                                        {
                                            classMember = classMemberContext;
                                            break;
                                        }
                                    }

                                    if (classMemberContext.varDeclare()?.NAME()?.GetText() != null)
                                    {
                                        if (classMemberContext.varDeclare().NAME().GetText() == memberClassName)
                                        {
                                            classMember = classMemberContext;
                                            break;
                                        }
                                    }
                                }
                            }

                            int classDeclIdx = classMember?.Start.StartIndex ?? classDecl.Start.StartIndex;
                            var start        = classDeclBhlDocument.GetLineColumn(classDeclIdx);
                            var startPos     = new Position {
                                line = (uint)start.Item1, character = (uint)start.Item2
                            };

                            return(RpcResult.Success(new Location
                            {
                                uri = classDeclBhlDocument.uri,
                                range = new Range
                                {
                                    start = startPos,
                                    end = startPos
                                }
                            }));
                        }
                    }

                    if (callExp != null)
                    {
                        string callExpName = callExp.NAME().GetText();

                        foreach (var doc in BHLSPWorkspace.self.ForEachBhlImports(document))
                        {
                            if (doc.FuncDecls.ContainsKey(callExpName))
                            {
                                funcDecl            = doc.FuncDecls[callExpName];
                                funcDeclBhlDocument = doc;
                                break;
                            }
                        }
                    }

                    if (statement != null && funcDecl == null)
                    {
                        string funcName = string.Empty;

                        string          pattern = @"([a-zA-Z_][a-zA-Z_0-9]*)(\({1}.*?)";
                        MatchCollection matches = Regex.Matches(statement.GetText(), pattern, RegexOptions.Multiline);
                        for (int i = 0; i < matches.Count; i++)
                        {
                            var m = matches[i];
                            if (m.Groups.Count > 1)
                            {
                                Group g = m.Groups[1];
                                funcName = g.Value;
                                break;
                            }
                        }

                        if (!string.IsNullOrEmpty(funcName))
                        {
                            foreach (var doc in BHLSPWorkspace.self.ForEachBhlImports(document))
                            {
                                if (doc.FuncDecls.ContainsKey(funcName))
                                {
                                    funcDecl            = doc.FuncDecls[funcName];
                                    funcDeclBhlDocument = doc;
                                    break;
                                }
                            }
                        }
                    }
                }
                else
                {
                    funcDeclBhlDocument = document;
                }

                if (funcDecl != null)
                {
                    var start    = funcDeclBhlDocument.GetLineColumn(funcDecl.Start.StartIndex);
                    var startPos = new Position {
                        line = (uint)start.Item1, character = (uint)start.Item2
                    };

                    return(RpcResult.Success(new Location
                    {
                        uri = funcDeclBhlDocument.uri,
                        range = new Range
                        {
                            start = startPos,
                            end = startPos
                        }
                    }));
                }
            }

            return(RpcResult.Success());
        }
Beispiel #6
0
        public override RpcResult SignatureHelp(SignatureHelpParams args)
        {
            BHLSPWorkspace.self.TryAddDocument(args.textDocument.uri);
            if (BHLSPWorkspace.self.FindDocument(args.textDocument.uri) is BHLTextDocument document)
            {
                int line      = (int)args.position.line;
                int character = (int)args.position.character;

                int start = document.GetIndex(line);
                int stop  = document.GetIndex(line, character);
                var text  = document.text;

                var    txtLine         = text.Substring(start, stop - start);
                string funcName        = string.Empty;
                uint   activeParameter = 0;

                if (txtLine.IndexOf("func", StringComparison.Ordinal) == -1)
                {
                    string          pattern = @"[a-zA-Z_][a-zA-Z_0-9]*\({1}.*?";
                    MatchCollection matches = Regex.Matches(txtLine, pattern, RegexOptions.Multiline);
                    for (int i = matches.Count - 1; i >= 0; i--)
                    {
                        var m = matches[i];
                        if (m.Index < character)
                        {
                            string v   = m.Value;
                            int    len = v.Length - 1;

                            if (len > 0)
                            {
                                funcName = txtLine.Substring(m.Index, len);
                                var funcDeclStr = txtLine.Substring(m.Index, Math.Max(0, character - m.Index));
                                activeParameter = (uint)Math.Max(0, funcDeclStr.Split(',').Length - 1);
                                break;
                            }
                        }
                    }
                }

                bhlParser.FuncDeclContext funcDecl = null;
                if (!string.IsNullOrEmpty(funcName))
                {
                    foreach (var doc in BHLSPWorkspace.self.ForEachBhlImports(document))
                    {
                        if (doc.FuncDecls.ContainsKey(funcName))
                        {
                            funcDecl = doc.FuncDecls[funcName];
                            break;
                        }
                    }
                }

                if (funcDecl != null)
                {
                    SignatureInformation signInfo = GetFuncSignInfo(funcDecl);
                    signInfo.activeParameter = activeParameter;

                    var result = new SignatureHelp();
                    result.activeSignature = 0;
                    result.signatures      = new[] { signInfo };
                    result.activeParameter = signInfo.activeParameter;

                    return(RpcResult.Success(result));
                }
            }

            return(RpcResult.Success());
        }