public override object VisitClassDecl(bhlParser.ClassDeclContext ctx) { var classDeclName = ctx.NAME(); if (classDeclName != null) { var classDeclNameText = classDeclName.GetText(); if (!classDecls.ContainsKey(classDeclNameText)) { classDecls.Add(classDeclNameText, ctx); } } AddSemanticToken(ctx.Start.StartIndex, classDeclName.Symbol.StartIndex - 1, SemanticTokenTypes.keyword); AddSemanticToken(classDeclName, SemanticTokenTypes.@class); if (ctx.extensions() != null) { for (int i = 0; i < ctx.extensions().NAME().Length; ++i) { var ext_name = ctx.extensions().NAME()[i]; AddSemanticToken(ext_name, SemanticTokenTypes.@class); } } foreach (var classMember in ctx.classBlock().classMembers().classMember()) { var classMemberVarDeclare = classMember.varDeclare(); if (classMemberVarDeclare != null) { Visit(classMemberVarDeclare.type()); AddSemanticToken(classMemberVarDeclare.NAME(), SemanticTokenTypes.variable, SemanticTokenModifiers.definition, SemanticTokenModifiers.@static); } } return(null); }
/** * 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()); }