private Range ReadRange() { var filePath = ReadUniqueString(); var startLine = ReadPackedInt(); var startColumn = ReadPackedInt(); var endLine = ReadPackedInt(); var endColumn = ReadPackedInt(); return(RangeModule.mkRange(filePath, PositionModule.mkPos(startLine, startColumn), PositionModule.mkPos(endLine, endColumn))); }
private ResolvedSymbols CreateFileResolvedSymbols() { var interruptChecker = new SeldomInterruptCheckerWithCheckTime(100); // todo: cancellation if (!(SourceFile.GetPrimaryPsiFile() is IFSharpFile fsFile)) { return(ResolvedSymbols.Empty); } var checkResults = CheckerService.ParseAndCheckFile(SourceFile, OpName)?.Value.CheckResults; var symbolUses = checkResults?.GetAllUsesOfAllSymbolsInFile(null); if (symbolUses == null) { return(ResolvedSymbols.Empty); } var document = SourceFile.Document; var lexer = fsFile.CachingLexer; var buffer = document.Buffer; var resolvedSymbols = new ResolvedSymbols(symbolUses.Length); foreach (var symbolUse in symbolUses) { var symbol = symbolUse.Symbol; var range = symbolUse.Range; var startOffset = document.GetOffset(range.Start); var endOffset = document.GetOffset(range.End); var mfv = symbol as FSharpMemberOrFunctionOrValue; var activePatternCase = symbol as FSharpActivePatternCase; if (symbolUse.IsFromDefinition) { if (mfv != null) { // workaround for auto-properties, see visualfsharp#3939 var mfvLogicalName = mfv.LogicalName; if (mfvLogicalName.EndsWith("@", StringComparison.Ordinal)) { continue; } // visualfsharp#3939 if (mfvLogicalName == "v" && resolvedSymbols.Declarations.ContainsKey(startOffset)) { continue; } if (mfvLogicalName == StandardMemberNames.ClassConstructor) { continue; } // visualfsharp#3943, visualfsharp#3933 if (mfvLogicalName != StandardMemberNames.Constructor && !(lexer.FindTokenAt(endOffset - 1) && (lexer.TokenType?.IsIdentifier ?? false) || mfv.IsActivePattern)) { continue; } if (mfvLogicalName == "Invoke" && (mfv.DeclaringEntity?.Value?.IsDelegate ?? false)) { continue; } var len = endOffset - startOffset; if (mfvLogicalName == "op_Multiply" && len == 3) { // The `*` pattern includes parens and is parsed as special token // let (*) (_, _) = () startOffset++; endOffset--; } } else if (activePatternCase != null) { // Skip active pattern cases bindings as these have incorrect ranges. // Active pattern cases uses inside bindings are currently marked as bindings so check the range. // https://github.com/Microsoft/visualfsharp/issues/4423 if (RangeModule.equals(activePatternCase.DeclarationLocation, range)) { var activePatternId = fsFile.GetContainingNodeAt <ActivePatternId>(new TreeOffset(endOffset - 1)); if (activePatternId == null) { continue; } var cases = activePatternId.Cases; var caseIndex = activePatternCase.Index; if (caseIndex < 0 || caseIndex >= cases.Count) { continue; } if (!(cases[caseIndex] is IActivePatternNamedCaseDeclaration caseDeclaration)) { continue; } var(caseStart, caseEnd) = caseDeclaration.GetTreeTextRange(); var caseStartOffset = caseStart.Offset; var caseTextRange = new TextRange(caseStartOffset, caseEnd.Offset); resolvedSymbols.Declarations[caseStartOffset] = new FSharpResolvedSymbolUse(symbolUse, caseTextRange); continue; } var caseUseInBindingRange = new TextRange(startOffset, endOffset); resolvedSymbols.Uses[startOffset] = new FSharpResolvedSymbolUse(symbolUse, caseUseInBindingRange); continue; } else { // workaround for compiler generated symbols (e.g. fields auto-properties) if (!(lexer.FindTokenAt(endOffset - 1) && (lexer.TokenType?.IsIdentifier ?? false))) { continue; } } var textRange = mfv != null ? new TextRange(startOffset, endOffset) : FixRange(startOffset, endOffset, null, buffer, lexer); startOffset = textRange.StartOffset; resolvedSymbols.Declarations[startOffset] = new FSharpResolvedSymbolUse(symbolUse, textRange); resolvedSymbols.Uses.Remove(startOffset); } else { // workaround for indexer properties, visualfsharp#3933 if (startOffset == endOffset || mfv is { IsProperty: true } && buffer[endOffset - 1] == ']')