示例#1
0
        /// <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);
        }
示例#2
0
        /// <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);
            }
        }
示例#3
0
        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);
        }
示例#4
0
        /// <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));
        }
示例#5
0
        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);
        }
示例#7
0
        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
            });
        }
示例#8
0
 public void AddSubsymbol(ISymbolInformation child)
 {
     if (Descendants == null)
     {
         Descendants = new List <ISymbolInformation>();
     }
     Descendants.Add(child);
 }
示例#9
0
        /// <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);
        }
示例#10
0
 /// <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);
     }
 }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#14
0
        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);
        }
示例#17
0
        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);
                }
            }
        }
示例#18
0
        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);
        }
示例#19
0
        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>()
            });
        }
示例#21
0
        /// <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));
        }
示例#22
0
        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);
        }
示例#23
0
        /// <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);
        }
示例#25
0
        /// <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);
        }
示例#26
0
        /// <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));
        }
示例#27
0
        /// <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);
        }
示例#28
0
        /// <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);
        }
示例#29
0
        /// <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);
        }
示例#30
0
 public ISymbolInformation GetSymbolAtPosition(ISymbolInformation rootEntry, IToken token)
 {
     return(GetSymbolAtPosition(rootEntry, new Uri(token.filename), token.line, token.col));
 }