/// <summary> /// Returns one symbol that matches the filter criteria and is child of the argument <c>symbol</c> /// </summary> private ISymbolInformation GetSingleChild(ISymbolInformation symbol, Predicate <ISymbolInformation> filter = null) { if (symbol == null) { throw new ArgumentNullException(nameof(symbol), Resources.ExceptionMessages.symbol_entrypoint_must_be_set); } filter = DefaultPredicateFilter(filter); ISymbolInformation child = symbol.Children?.FirstOrDefault(filter.Invoke); if (child != null) { return(child); } if (symbol.HasInheritedMembers) { foreach (var baseScope in symbol.BaseClasses) { var baseClassSymbol = baseScope?.Children?.FirstOrDefault(filter.Invoke); if (baseClassSymbol != null) { return(baseClassSymbol); } } } return(null); }
/// <summary> /// Call <c>GetSupposedDesire</c> before this function to get the <c>CompletionType</c> parameter. /// Call <c>GetWrappingEntrypointSymbol</c> to get the entry point parameter. /// </summary> private IEnumerable <ISymbolInformation> GetSymbols(CompletionType desire, ISymbolInformation wrappingEntrypointSymbol) { switch (desire) { case CompletionType.AfterDot: if (ExtractedSymbol == "this") { ISymbolInformation declarationOfSymbolBeforeDot = SymbolTableManager.GetEnclosingClass(wrappingEntrypointSymbol); return(GetSymbolsProperties(declarationOfSymbolBeforeDot)); } else { var declarationOfSymbolBeforeDot = SymbolTableManager.GetClosestSymbolByName(wrappingEntrypointSymbol, ExtractedSymbol); var classSymbol = SymbolTableManager.GetClassOriginFromSymbol(declarationOfSymbolBeforeDot); return(GetSymbolsProperties(classSymbol)); } case CompletionType.AfterNew: return(GetClassSymbolsInScope(SymbolTableManager, wrappingEntrypointSymbol)); case CompletionType.AllInScope: return(GetAllSymbolsInScope(SymbolTableManager, wrappingEntrypointSymbol)); default: throw new ArgumentException(Resources.ExceptionMessages.completion_not_yet_supported); } }
private IEnumerable <string> GetSymbolsAsList(string f) { var physFile = new PhysicalFile { Filepath = f, Sourcecode = File.ReadAllText(f) }; var dtu = new DafnyTranslationUnit(physFile); var dafnyProg = dtu.Verify().DafnyProgram; ISymbolTableGenerator st = new SymbolTableGenerator(dafnyProg); ISymbolInformation root = st.GenerateSymbolTable(); ISymbolTableManager sm = new SymbolTableManager(root); ISymbolNavigator navigator = new SymbolNavigator(); List <ISymbolInformation> symbols = new List <ISymbolInformation>(); foreach (var modul in root.Children) { symbols.AddRange(navigator.TopDownAll(modul)); } var actual = symbols.Select(x => x.ToDebugString()).ToList(); Console.WriteLine("SymboleTable for " + f); Console.Write(((SymbolTableManager)sm).CreateDebugReadOut()); return(actual); }
/// <summary> /// Checks whether a position is within the full range of a symbol. /// The full range starts at the identifier and stops at the body end. /// If there is no body, the identifier end counts as the full range. /// </summary> public static bool PositionIsWithinSymbolTotalRange(ISymbolInformation s, Uri file, int line, int character) { if (!IsSameFile(s, file)) { return(false); } int startLine = s.Line; int startCol = s.Column; int endLine; int endCol; if (s.HasBody) { endLine = s.Position.BodyEndToken.line; endCol = s.Position.BodyEndToken.col; } else { endLine = s.Line; endCol = s.Column + s.Name.Length; } int targetLine = line; int targetCol = character; return(Wraps(startLine, startCol, endLine, endCol, targetLine, targetCol)); }
public override void Visit(ClassDecl o) { var preDeclaredSymbol = FindDeclaration(o.Name, SurroundingScope, Kind.Class); if (o.TraitsTyp.Any()) { preDeclaredSymbol.BaseClasses = new List <ISymbolInformation>(); foreach (var baseClassType in o.TraitsTyp) { var baseClassIdentifier = baseClassType as UserDefinedType; ISymbolInformation baseSymbol = FindDeclaration(baseClassIdentifier?.Name, SurroundingScope); preDeclaredSymbol.BaseClasses.Add(baseSymbol); var t = CreateSymbol( name: baseClassIdentifier?.Name, positionAsToken: baseClassIdentifier?.tok, bodyStartPosAsToken: null, bodyEndPosAsToken: null, kind: Kind.Class, type: baseClassType, isDeclaration: false, declarationSymbol: baseSymbol, addUsageAtDeclaration: true, canHaveChildren: false, canBeUsed: false ); t.Parent = preDeclaredSymbol; } } SetScope(preDeclaredSymbol); SetClass(preDeclaredSymbol); }
private static MarkupContent CreateMarkupContent(ISymbolInformation symbol) { string type = symbol.Type?.ToString(); if (string.IsNullOrEmpty(type) || type == "?") { type = Resources.LoggingMessages.hover_unknown; } string declaration = symbol.IsDeclaration ? Resources.LoggingMessages.hover_isDeclaration : symbol.DeclarationOrigin.PositionToFormattedString(); string parameters = ""; if (symbol.Kind == Kind.Method || symbol.Kind == Kind.Function) { parameters += "("; if (symbol?.DeclarationOrigin?.Params != null) { parameters += string.Join(", ", symbol.DeclarationOrigin.Params.Select(parameter => parameter.Name + ": " + parameter.Type)); } parameters += ")"; } var formattedContent = new MarkupContent(); formattedContent.Kind = MarkupKind.Markdown; formattedContent.Value = $" **`{symbol.Name + parameters}`** *({symbol.PositionToFormattedString()})*\n" + $"* **{Resources.LoggingMessages.hover_type}:** {type}\n" + $"* **{Resources.LoggingMessages.hover_kind}:** {symbol.Kind}\n" + $"* **{Resources.LoggingMessages.hover_scope}:** `{symbol.Parent.Name}`\n" + $"* **{Resources.LoggingMessages.hover_declaration}:** {declaration}"; return(formattedContent); }
private CompletionItem CreateCompletionItem(ISymbolInformation symbol, CompletionType desire) { CompletionItemKind kind = Enum.TryParse(symbol.Kind.ToString(), true, out kind) ? kind : CompletionItemKind.Reference; var insertCode = GetCompletionCodeFragment(symbol, desire); var details = ""; if (symbol.Params != null) { details += LoggingMessages.completion_params + ": " + string.Join(", ", symbol?.Params.Select(parameter => parameter.Name + ": " + parameter.Type)) + "\n "; } #if DEBUG details += $"Kind: { symbol.Kind } \n Parent: { symbol.Parent.Name }"; #endif return (new CompletionItem { Label = symbol.Name, Kind = kind, InsertText = insertCode, Detail = details }); }
public void AddSubsymbol(ISymbolInformation child) { if (Descendants == null) { Descendants = new List <ISymbolInformation>(); } Descendants.Add(child); }
/// <summary> /// Builds a short fake symbol table which can be used for testing. /// </summary> /// <returns>root symbol of the fake table</returns> /// <remarks> /// root /// another decl /// use1 use2 /// </remarks> public ISymbolInformation GenerateSymbolTable() { ISymbolInformation root = SymbolTableGenerator.GetEmptySymbolTable(); SymbolInformation decl = new SymbolInformation { Position = new TokenPosition() { Token = new Token(1, 11) }, Name = "barapapa", Parent = root }; decl.DeclarationOrigin = decl; SymbolInformation use1 = new SymbolInformation { Position = new TokenPosition() { Token = new Token(2, 22) }, Name = "barapapa", Parent = root, DeclarationOrigin = decl }; SymbolInformation use2 = new SymbolInformation { Position = new TokenPosition() { Token = new Token(3, 33) }, Name = "barapapa", Parent = root, DeclarationOrigin = decl }; SymbolInformation anotherSymbol = new SymbolInformation { Position = new TokenPosition() { Token = new Token(4, 443) }, Name = "bubu", Parent = root, }; anotherSymbol.DeclarationOrigin = anotherSymbol; root.ChildrenHash = new Dictionary <string, ISymbolInformation>(); root.ChildrenHash.Add("barapapa", decl); root.ChildrenHash.Add("bubu", anotherSymbol); decl.Usages = new List <ISymbolInformation> { use1, use2 }; return(root); }
/// <summary> /// Sets the SymbolTableManager Property. /// Makes use of the dafnyProgram inside the Result property. /// </summary> private void AddSymbolTable() { if (Result.TranslationStatus >= TranslationStatus.Resolved && Result.DafnyProgram != null) { SymbolTableGenerator s = new SymbolTableGenerator(Result.DafnyProgram); ISymbolInformation rootnode = s.GenerateSymbolTable(); SymbolTableManager = new SymbolTableManager(rootnode); } }
public void GetSymbolByPositionNotExist() { SymbolInformationFake rootEntry = new SymbolInformationFake(1, 0, 1, 0, 5, 0, defaultFile, "Parent"); SymbolInformationFake mySymbol = new SymbolInformationFake(2, 0, 2, 0, 5, 0, defaultFile, "Child"); rootEntry.AddChild(mySymbol); ISymbolInformation symbol = nav.GetSymbolAtPosition(rootEntry, defaultUri, 6, 9); Assert.IsNull(symbol); }
public void GetSymbolByPositionNested() { SymbolInformationFake rootEntry = new SymbolInformationFake(1, 0, 1, 0, 5, 1, defaultFile, "Parent"); SymbolInformationFake mySymbol = new SymbolInformationFake(2, 0, 2, 0, 5, 1, defaultFile, "Child"); rootEntry.AddChild(mySymbol); ISymbolInformation symbol = nav.GetSymbolAtPosition(rootEntry, defaultUri, 2, 1); Assert.AreEqual(mySymbol, symbol); }
public void GetTopDownSymbolEmptyLine() { SymbolInformationFake rootEntry = new SymbolInformationFake(1, 0, 1, 0, 10, 0, defaultFile, "Parent"); rootEntry.AddChild(new SymbolInformationFake(1, 0, 1, 0, 4, 0, defaultFile, "SubParent1")); rootEntry.AddChild(new SymbolInformationFake(6, 0, 6, 0, 9, 0, defaultFile, "SubParent2")); ISymbolInformation symbol = nav.TopDown(rootEntry, defaultUri, 5, 0); Assert.AreEqual(rootEntry, symbol); }
public void GetTopDownSymbolSimple() { SymbolInformationFake rootEntry = new SymbolInformationFake(1, 0, 1, 0, 3, 0, defaultFile, "Parent"); SymbolInformationFake mySymbol = new SymbolInformationFake(2, 0, 2, 0, 2, 0, defaultFile, "Child"); rootEntry.AddChild(mySymbol); ISymbolInformation symbol = nav.TopDown(rootEntry, defaultUri, 2, 0); Assert.AreEqual(mySymbol, symbol); }
protected LanguageServerVisitorBase(ISymbolInformation entryPoint) { SetScope(entryPoint); var root = entryPoint; while (root.Kind != Kind.RootNode) { root = root.Parent; } RootNode = root; }
public ISymbolInformation GetSymbolByPosition(Uri file, int line, int character) { if (_returnNull) { return(null); } ISymbolInformation root = new FakeSymbolTable().GenerateSymbolTable(); ISymbolInformation declaration = root["barapapa"]; ISymbolInformation notDeclaration = declaration.Usages[0]; return(_returnDeclaration ? declaration : notDeclaration); }
private IEnumerable <ISymbolInformation> GetSymbolsProperties(ISymbolInformation entryPoint) { if (entryPoint == null) { throw new InvalidOperationException(Resources.ExceptionMessages.no_symbol_before_fot_found); } foreach (var suggestionElement in entryPoint.Children) { if (IsNoDefaultNamespace(suggestionElement)) { yield return(suggestionElement); } } }
public void GetTopDownSymbolDeep() { SymbolInformationFake rootEntry = new SymbolInformationFake(1, 0, 1, 0, 10, 0, defaultFile, "Parent"); rootEntry.AddChild(new SymbolInformationFake(1, 0, 1, 0, 2, 0, defaultFile, "SubParent1")); rootEntry.AddChild(new SymbolInformationFake(3, 0, 3, 0, 4, 0, defaultFile, "SubParent2")); var subParent = new SymbolInformationFake(5, 0, 5, 0, 10, 0, defaultFile, "RightSubParent"); rootEntry.AddChild(subParent); SymbolInformationFake mySymbol = new SymbolInformationFake(6, 0, 6, 0, 10, 0, defaultFile, "MyChild"); subParent.AddChild(mySymbol); ISymbolInformation symbol = nav.TopDown(rootEntry, defaultUri, 9, 0); Assert.AreEqual(mySymbol, symbol); }
private string GetCompletionCodeFragment(ISymbolInformation symbol, CompletionType desire) { switch (desire) { case CompletionType.AfterNew: return(symbol.Name + "()"); case CompletionType.AfterDot: return((symbol.Kind == Kind.Method || symbol.Kind == Kind.Function) ? (symbol.Name + "()") : symbol.Name); default: return(symbol.Name); } }
protected ISymbolInformation FindDeclaration(string target, ISymbolInformation scope, Kind?kind = null) { ISymbolNavigator navigator = new SymbolNavigator(); bool filter(ISymbolInformation s) => s.Name == target && s.IsDeclaration && (kind == null || s.Kind == kind); return(navigator.BottomUpFirst(scope, filter) ?? new SymbolInformation { Name = Resources.SymbolTableStrings.declaration_not_found, Position = new TokenPosition() { Token = new Token(0, 0) }, ChildrenHash = new Dictionary <string, ISymbolInformation>(), Usages = new List <ISymbolInformation>() }); }
/// <summary> /// Checks whether a position is within the identifier of a symbol. /// If the position is within the symbol's body, this method will return false. /// </summary> public static bool PositionIsWithinSymbolIdentifier(ISymbolInformation s, Uri file, int line, int character) { if (!IsSameFile(s, file)) { return(false); } int startLine = s.Line; int startCol = s.Column; int endLine = s.Line; int endCol = s.Column + s.Name.Length; int targetLine = line; int targetCol = character; return(Wraps(startLine, startCol, endLine, endCol, targetLine, targetCol)); }
private IEnumerable <ISymbolInformation> GetAllChildren(ISymbolInformation symbol, Predicate <ISymbolInformation> filter = null) { if (symbol == null) { throw new ArgumentNullException(nameof(symbol), Resources.ExceptionMessages.symbol_entrypoint_must_be_set); } filter = DefaultPredicateFilter(filter); var list = symbol.Children?.Where(filter.Invoke).ToList() ?? new List <ISymbolInformation>(); if (symbol.HasInheritedMembers) { foreach (var baseScope in symbol.BaseClasses) { list.AddRange(baseScope?.Children?.Where(filter.Invoke) ?? throw new InvalidOperationException(Resources.ExceptionMessages.invalid_filter_operation)); } } return(list); }
/// <summary> /// Searches all symbols (not just definitions) from top to bottom. /// An optional filter for the conditions can be specified. /// </summary> public List <ISymbolInformation> TopDownAll(ISymbolInformation symbol, Predicate <ISymbolInformation> filter = null) { filter = DefaultPredicateFilter(filter); List <ISymbolInformation> symbolList = new List <ISymbolInformation>(); if (symbol != null && filter.Invoke(symbol)) { symbolList.Add(symbol); } if (symbol?.Descendants == null) { return(symbolList); } foreach (var child in symbol.Descendants) { symbolList.AddRange(TopDownAll(child, filter)); } return(symbolList); }
/// <summary> /// Generates the symbolt able for the provdied Dafny Program. /// </summary> /// <returns>A single symbol acting as the root entrypoint (aka global namespace) for that dafny program.</returns> public ISymbolInformation GenerateSymbolTable() { var modules = DafnyProgram.Modules().ToList(); modules.Sort((m1, m2) => Depth(m1) - Depth(m2)); foreach (var module in modules) { ISymbolInformation rootForVisitor = GetEntryPoint(module); var declarationVisitor = new LanguageServerDeclarationVisitor(rootForVisitor); module.Accept(declarationVisitor); } foreach (var module in modules) { ISymbolInformation rootForVisitor = GetEntryPoint(module); var deepVisitor = new SymbolTableVisitorEverythingButDeclarations(rootForVisitor); module.Accept(deepVisitor); } return(DafnyProgramRootSymbol); }
/// <summary> /// Searches the tree down. Returns the found symbol or null. /// Only takes definitions into account. /// If you would like all symbols, not only definitions, use <c>GetSymbolAtPosition</c>. /// </summary> public ISymbolInformation TopDown(ISymbolInformation rootEntry, Uri file, int line, int character) { if (rootEntry == null) { return(null); } ISymbolInformation bestMatch = null; if (SymbolUtil.PositionIsWithinSymbolTotalRange(rootEntry, file, line, character)) { bestMatch = rootEntry; } foreach (var child in rootEntry.Children) { if (SymbolUtil.PositionIsWithinSymbolTotalRange(child, file, line, character)) { bestMatch = child; if (child.HasChildren) { var match = TopDown(child, file, line, character); bestMatch = match ?? bestMatch; } } // in case no better match was found, // check default scope too if ( (bestMatch == null || bestMatch.Equals(rootEntry)) && (child.Name == Resources.SymbolTableStrings.default_class || child.Name == Resources.SymbolTableStrings.default_module) && (child.Children?.Any() ?? false) ) { bestMatch = TopDown(child, file, line, character); } } return(bestMatch); }
/// <summary> /// Checks whether a position is within the body of a symbol. /// If the symbol has no body, false is returned. /// </summary> public static bool PositionIsWithinSymbolBody(ISymbolInformation s, Uri file, int line, int character) { if (!IsSameFile(s, file)) { return(false); } if (!s.HasBody) { return(false); } int startLine = s.Position.BodyStartToken.line; int startCol = s.Position.BodyStartToken.col; int endLine = s.Position.BodyEndToken.line; int endCol = s.Position.BodyEndToken.col; int targetLine = line; int targetCol = character; return(Wraps(startLine, startCol, endLine, endCol, targetLine, targetCol)); }
/// <summary> /// Starts a search from the inside out. /// Aborts the search when the first symbol fulfilling the filter is found. /// An optional filter for the conditions can be specified. /// </summary> public ISymbolInformation BottomUpFirst(ISymbolInformation entryPoint, Predicate <ISymbolInformation> filter = null) { filter = DefaultPredicateFilter(filter); var symbol = entryPoint; do { var result = GetSingleChild(symbol, filter); if (result != null) { return(result); } symbol = symbol.Parent; } while (symbol != null); if (entryPoint.Kind != Kind.RootNode) { return(GetSingleChild(entryPoint.AssociatedDefaultClass, filter)); } return(null); }
/// <summary> /// Searches the tree downwards to match a specific location. /// Only symbols that wrap the location are searched. /// <returns> Returns the match oder null.</returns> /// This will find all symbols, not only definitions. /// If you would like to search for definitions only, use <c>TopDown</c> /// </summary> public ISymbolInformation GetSymbolAtPosition(ISymbolInformation rootEntry, Uri file, int line, int character) { if (rootEntry == null || (!SymbolUtil.PositionIsWithinSymbolTotalRange(rootEntry, file, line, character) && (rootEntry.Name != Resources.SymbolTableStrings.default_module))) { return(null); } var wrappingSymbol = TopDown(rootEntry, file, line, character); if (wrappingSymbol?.Descendants != null) { foreach (var symbol in wrappingSymbol.Descendants) { if (SymbolUtil.PositionIsWithinSymbolIdentifier(symbol, file, line, character)) { return(symbol); } } } if (line == wrappingSymbol?.Line && character <= wrappingSymbol.IdentifierEndColumn) { return(wrappingSymbol); } return(null); }
/// <summary> /// Starts a search from the inside out. Returns all symbols that match a filter. /// An optional filter for the conditions can be specified. /// </summary> public List <ISymbolInformation> BottomUpAll(ISymbolInformation symbol, Predicate <ISymbolInformation> filter = null) { filter = DefaultPredicateFilter(filter); List <ISymbolInformation> list = new List <ISymbolInformation>(); if (symbol == null) { return(list); } if (symbol.Name == Resources.SymbolTableStrings.default_module) { list.AddRange(GetAllChildren(symbol.AssociatedDefaultClass, filter)); } do { list.AddRange(GetAllChildren(symbol, filter)); symbol = symbol.Parent; } while (symbol != null); return(list); }
public ISymbolInformation GetSymbolAtPosition(ISymbolInformation rootEntry, IToken token) { return(GetSymbolAtPosition(rootEntry, new Uri(token.filename), token.line, token.col)); }