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)); }
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()); }