Beispiel #1
0
            static SSAType getTypeRef(FrontendStructType t, int depth)
            {
                bool packed = t.packed;
                var  result = new StructType(packed);

                foreach (var f in t.fields)
                {
                    result.elementTypes.Add(getTypeRef(f.type, depth + 1));
                }
                return(result);
            }
    public async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken)
    {
        var documentPath = DocumentUri.GetFileSystemPath(request.TextDocument.Uri);

        if (string.IsNullOrEmpty(documentPath))
        {
            return(new CompletionList());
        }
        var(rootScope, tc) = buffers.GetScope(documentPath);
        if (rootScope == null)
        {
            return(new CompletionList());
        }

        var scope = GetCurrentScope(rootScope, (int)request.Position.Character, (int)request.Position.Line, documentPath);

        var completions = new List <CompletionItem>();

        if (request.Context.TriggerKind == CompletionTriggerKind.TriggerCharacter)
        {
            var text    = buffers.GetBuffer(documentPath);
            var charIdx = (int)request.Position.Character;
            var lineIdx = (int)request.Position.Line;
            var lines   = text.Split(System.Environment.NewLine);
            var line    = default(string);
            if (lineIdx >= 0 && lineIdx < lines.Length)
            {
                line = lines[lineIdx];
            }
            if (line == null)
            {
                return(new CompletionList(completions));
            }

            if (request.Context.TriggerCharacter == " ")
            {
                charIdx--;
                if (line.ElementAtOrDefault(charIdx) == ' ' && line.ElementAtOrDefault(charIdx - 1) == ':')
                {
                    AddToScope(scope, AddToScopeFlags.Types | AddToScopeFlags.Recursive, completions, tc);
                    return(new CompletionList(completions));
                }
                if (line.ElementAtOrDefault(charIdx) == ' ' && line.ElementAtOrDefault(charIdx - 1) == '>' && line.ElementAtOrDefault(charIdx - 2) == '=')
                {
                    AddToScope(scope, AddToScopeFlags.Types | AddToScopeFlags.Recursive, completions, tc);
                    return(new CompletionList(completions));
                }
            }
            if (request.Context.TriggerCharacter == ">")
            {
                charIdx--;
                if (line.ElementAtOrDefault(charIdx) == '>' && line.ElementAtOrDefault(charIdx - 1) == '=')
                {
                    AddToScope(scope, AddToScopeFlags.Types | AddToScopeFlags.Recursive | AddToScopeFlags.AddSpaceToType, completions, tc);
                    return(new CompletionList(completions));
                }
            }
            if (request.Context.TriggerCharacter == "@")
            {
                AddToScope(scope, AddToScopeFlags.Types | AddToScopeFlags.Recursive, completions, tc);
                return(new CompletionList(completions));
            }
            if (request.Context.TriggerCharacter == ":")
            {
                charIdx--;
                if (line.ElementAtOrDefault(charIdx) == ':' && line.ElementAtOrDefault(charIdx - 1) != ':')
                {
                    AddToScope(scope, AddToScopeFlags.Types | AddToScopeFlags.Recursive | AddToScopeFlags.AddSpaceToType, completions, tc);
                    return(new CompletionList(completions));
                }
                if (line.ElementAtOrDefault(charIdx) != ':' || line.ElementAtOrDefault(charIdx - 1) != ':')
                {
                    return(new CompletionList(completions));
                }

                charIdx = charIdx - 2;
                List <string> query = new List <string>();
                while (true)
                {
                    var current = "";
                    while (charIdx >= 0 && Token.isIdentifierChar(line[charIdx]))
                    {
                        current = line[charIdx] + current;
                        charIdx--;
                    }
                    if (string.IsNullOrWhiteSpace(current))
                    {
                        break;
                    }
                    else
                    {
                        query.Add(current);
                    }
                    while (charIdx >= 0 && char.IsWhiteSpace(line[charIdx]))
                    {
                        charIdx--;
                    }
                    if (charIdx <= 1 || line[charIdx] != ':' || line[charIdx - 1] != ':')
                    {
                        break;
                    }
                    charIdx -= 2;
                }
                if (query.Count > 0)
                {
                    var mod = scope.GetModule(query);
                    if (mod != null)
                    {
                        AddToScope(mod.scope, AddToScopeFlags.Types | AddToScopeFlags.Variables, completions, tc);
                    }
                }
                return(new CompletionList(completions));
            }

            if (request.Context.TriggerCharacter == ".")
            {
                charIdx = System.Math.Clamp(charIdx, 0, line.Length - 1);
                while (charIdx >= 0 && line[charIdx] != '.')
                {
                    charIdx--;
                }
                if (charIdx >= 0 && charIdx < line.Length)
                {
                    if (line[charIdx] == '.')
                    {
                        charIdx--;
                    }
                }
                List <string> query = new List <string>();
                while (true)
                {
                    var current = "";
                    while (charIdx >= 0 && Token.isIdentifierChar(line[charIdx]))
                    {
                        current = line[charIdx] + current;
                        charIdx--;
                    }
                    if (string.IsNullOrWhiteSpace(current))
                    {
                        break;
                    }
                    else
                    {
                        query.Add(current);
                    }
                    while (charIdx >= 0 && char.IsWhiteSpace(line[charIdx]))
                    {
                        charIdx--;
                    }
                    if (charIdx <= 0 || line[charIdx] != '.')
                    {
                        break;
                    }
                    charIdx--;
                }
                List <string> modPath = new List <string>();
                if (line.ElementAtOrDefault(charIdx) == ':' && line.ElementAtOrDefault(charIdx - 1) == ':')
                {
                    charIdx -= 2;

                    while (true)
                    {
                        var current = "";
                        while (charIdx >= 0 && Token.isIdentifierChar(line[charIdx]))
                        {
                            current = line[charIdx] + current;
                            charIdx--;
                        }
                        if (string.IsNullOrWhiteSpace(current))
                        {
                            break;
                        }
                        else
                        {
                            modPath.Add(current);
                        }
                        while (charIdx >= 0 && char.IsWhiteSpace(line[charIdx]))
                        {
                            charIdx--;
                        }
                        if (charIdx <= 1 || line[charIdx] != ':' || line[charIdx - 1] != ':')
                        {
                            break;
                        }
                        charIdx -= 2;
                    }
                }


                if (query.Count > 0)
                {
                    FrontendStructType st = null;
                    for (int i = query.Count - 1; i >= 0; --i)
                    {
                        var current = query[i];
                        if (i == query.Count - 1)
                        {
                            if (modPath.Count > 0)
                            {
                                scope = scope.GetModule(modPath)?.scope;
                                if (scope == null)
                                {
                                    break;
                                }
                            }
                            var v = scope.GetVar(current, Token.Undefined)?.First;
                            if (v == null)
                            {
                                st = null;
                                break;
                            }
                            FrontendType vt;
                            if (v.node == null)
                            {
                                vt = v.type;
                            }
                            else
                            {
                                vt = tc.GetNodeType(v.node);
                            }
                            st = vt as FrontendStructType;

                            if (st == null && vt is FrontendPointerType pt)
                            {
                                st = pt.elementType as FrontendStructType;
                            }
                        }
                        else
                        {
                            var f = st.fields.Where(f => f.name == current).FirstOrDefault();
                            if (f == null)
                            {
                                st = null;
                                break;
                            }
                            st = f.type as FrontendStructType;
                            if (st == null && f.type is FrontendPointerType pt)
                            {
                                st = pt.elementType as FrontendStructType;
                            }
                        }
                        if (st == null)
                        {
                            break;
                        }
                    }
                    if (st != null)
                    {
                        foreach (var f in st.fields)
                        {
                            var item = new CompletionItem
                            {
                                Kind   = CompletionItemKind.Field,
                                Label  = f.name,
                                Detail = f.type.ToString()
                            };
                            completions.Add(item);
                        }
                    }
                }
            }
        }

        if (request.Context.TriggerKind == CompletionTriggerKind.Invoked || request.Context.TriggerKind == CompletionTriggerKind.TriggerForIncompleteCompletions)
        {
            completions.Add(Keyword("let"));
            completions.Add(Keyword("var"));
            completions.Add(Keyword("struct"));
            completions.Add(Keyword("enum"));
            completions.Add(Keyword("fun"));
            completions.Add(Keyword("return"));
            completions.Add(Keyword("true"));
            completions.Add(Keyword("false"));
            completions.Add(Keyword("if"));
            completions.Add(Keyword("elif"));
            completions.Add(Keyword("else"));
            completions.Add(Keyword("for"));
            completions.Add(Keyword("while"));
            completions.Add(Keyword("break"));
            completions.Add(Keyword("continue"));
            completions.Add(Keyword("size_of"));
            completions.Add(Keyword("extern"));
            completions.Add(Keyword("import"));
            completions.Add(Keyword("mod"));
            completions.Add(Keyword("with"));
            AddToScope(scope, AddToScopeFlags.Variables | AddToScopeFlags.Modules | AddToScopeFlags.Recursive, completions, tc);
        }
        return(new CompletionList(completions));
    }
Beispiel #3
0
    public async Task <SignatureHelp> Handle(SignatureHelpParams request, CancellationToken cancellationToken)
    {
        var documentPath = DocumentUri.GetFileSystemPath(request.TextDocument.Uri);

        if (string.IsNullOrEmpty(documentPath))
        {
            return(new SignatureHelp());
        }
        var(rootScope, tc) = buffers.GetScope(documentPath);
        if (rootScope == null)
        {
            return(new SignatureHelp());
        }

        var scope = GetCurrentScope(rootScope, (int)request.Position.Character, (int)request.Position.Line, documentPath);

        var text    = buffers.GetBuffer(documentPath);
        var charIdx = (int)request.Position.Character;
        var lineIdx = (int)request.Position.Line;
        var lines   = text.Split(System.Environment.NewLine);
        var line    = default(string);

        if (lineIdx >= 0 && lineIdx < lines.Length)
        {
            line = lines[lineIdx];
        }
        if (line == null)
        {
            return(new SignatureHelp());
        }

        charIdx = System.Math.Clamp(charIdx, 0, line.Length - 1);
        int activeParam = 0;

        while (charIdx >= 0 && line[charIdx] != '(')
        {
            if (line[charIdx] == ',')
            {
                activeParam++;
            }
            charIdx--;
        }
        if (charIdx >= 0 && charIdx < line.Length)
        {
            if (line[charIdx] == '(')
            {
                charIdx--;
            }
        }
        List <string> query = new List <string>();

        while (true)
        {
            var current = "";
            while (charIdx >= 0 && Token.isIdentifierChar(line[charIdx]))
            {
                current = line[charIdx] + current;
                charIdx--;
            }
            if (string.IsNullOrWhiteSpace(current))
            {
                break;
            }
            else
            {
                query.Add(current);
            }
            while (charIdx >= 0 && char.IsWhiteSpace(line[charIdx]))
            {
                charIdx--;
            }
            if (charIdx <= 0 || line[charIdx] != '.')
            {
                break;
            }
            charIdx--;
        }
        List <string> modPath = new List <string>();

        if (line.ElementAtOrDefault(charIdx) == ':' && line.ElementAtOrDefault(charIdx - 1) == ':')
        {
            charIdx -= 2;

            while (true)
            {
                var current = "";
                while (charIdx >= 0 && Token.isIdentifierChar(line[charIdx]))
                {
                    current = line[charIdx] + current;
                    charIdx--;
                }
                if (string.IsNullOrWhiteSpace(current))
                {
                    break;
                }
                else
                {
                    modPath.Add(current);
                }
                while (charIdx >= 0 && char.IsWhiteSpace(line[charIdx]))
                {
                    charIdx--;
                }
                if (charIdx <= 1 || line[charIdx] != ':' || line[charIdx - 1] != ':')
                {
                    break;
                }
                charIdx -= 2;
            }
        }

        if (query.Count > 0)
        {
            Scope.OverloadedVariableDefinition vd = null;
            FrontendStructType st = null;
            for (int i = query.Count - 1; i >= 0; --i)
            {
                var          current = query[i];
                FrontendType vt;
                if (i == query.Count - 1)
                {
                    if (modPath.Count > 0)
                    {
                        scope = scope.GetModule(modPath)?.scope;
                        if (scope == null)
                        {
                            break;
                        }
                    }
                    if (i == 0)
                    {
                        vd = scope.GetVar(current, Token.Undefined);
                    }
                    else
                    {
                        var v = scope.GetVar(current, Token.Undefined)?.First;
                        if (v == null)
                        {
                            st = null;
                            break;
                        }
                        if (v.node == null)
                        {
                            vt = v.type;
                        }
                        else
                        {
                            vt = tc.GetNodeType(v.node);
                        }
                        st = vt as FrontendStructType;
                        if (st == null && vt is FrontendPointerType pt)
                        {
                            st = pt.elementType as FrontendStructType;
                        }
                        if (st == null)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    if (i == 0)
                    {
                        vd = scope.GetVar(current, Token.Undefined);
                    }
                    else
                    {
                        var f = st.fields.Where(f => f.name == current).FirstOrDefault();
                        if (f == null)
                        {
                            st = null;
                            break;
                        }
                        vt = f.type;
                        st = vt as FrontendStructType;
                        if (st == null && vt is FrontendPointerType pt)
                        {
                            st = pt.elementType as FrontendStructType;
                        }
                        if (st == null)
                        {
                            break;
                        }
                    }
                }
            }
            if (vd != null)
            {
                var infos = new List <SignatureInformation>();
                foreach (var v in vd.variables)
                {
                    FrontendFunctionType ft;
                    if (v.node == null)
                    {
                        ft = v.type as FrontendFunctionType;
                    }
                    else
                    {
                        ft = tc.GetNodeType(v.node) as FrontendFunctionType;
                    }
                    if (ft != null)
                    {
                        var info        = new SignatureInformation();
                        var parameInfos = new List <ParameterInformation>();
                        var funName     = ft.funName;
                        if (string.IsNullOrEmpty(funName))
                        {
                            funName = v.name;
                        }
                        var funString = $"{funName}(";
                        for (int i = 0; i < ft.parameters.Count; ++i)
                        {
                            var p           = ft.parameters[i];
                            var paramString = $"{p.name}: {p.type}";

                            parameInfos.Add(
                                new ParameterInformation()
                            {
                                Label = paramString,
                            }
                                );
                            funString += paramString;
                            if (i < ft.parameters.Count - 1)
                            {
                                funString += "; ";
                            }
                        }
                        funString      += $") => {ft.returnType}";
                        info.Label      = funString;
                        info.Parameters = parameInfos;
                        infos.Add(info);
                    }
                }
                var result = new SignatureHelp
                {
                    ActiveParameter = activeParam,
                    Signatures      = new Container <SignatureInformation>(infos)
                };
                return(result);
            }
        }
        return(new SignatureHelp());
    }