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