提交 7f6fdd04 编写于 作者: R Ravi Chande

Merge pull request #11398 from rchande/fixsymbolidcrash

Fix #11193
......@@ -349,7 +349,7 @@ private void EncodeMethod(IMethodSymbol symbol)
EncodeParameters(symbol.Parameters);
// return types are not use for overloading in C# and VB
// return types are not use for overloading in C# and VB
#if false
if (!symbol.ReturnsVoid)
{
......@@ -656,7 +656,7 @@ private static int GetInteriorSymbolOccurrence(ISymbol symbol)
// sym.Equals(symbol) not working for locals of empty anonymous types?
// since this code is only called on source that originated symbol, then spans should match
if (sym.DeclaringSyntaxReferences.Length > 0
if (sym.DeclaringSyntaxReferences.Length > 0
&& symbol.DeclaringSyntaxReferences.Length > 0
&& sym.DeclaringSyntaxReferences[0].Span == symbol.DeclaringSyntaxReferences[0].Span)
{
......@@ -714,6 +714,26 @@ private static void GetInteriorSymbols(ISymbol containingSymbol, List<ISymbol> s
{
foreach (var declaringLocation in containingSymbol.DeclaringSyntaxReferences)
{
// This operation can potentially fail. If containingSymbol came from
// a SpeculativeSemanticModel, containingSymbol.ContainingAssembly.Compilation
// may not have been rebuilt to reflect the trees used by the
// SpeculativeSemanticModel to produce containingSymbol. In that case,
// asking the ContainingAssembly's complation for a SemanticModel based
// on trees for containingSymbol with throw an ArgumentException.
// Unfortunately, the best way to avoid this (currently) is to see if
// we're asking for a model for a tree that's part of the compilation.
// (There's no way to get back to a SemanticModel from a symbol).
// TODO (rchande): It might be better to call compilation.GetSemanticModel
// and catch the ArgumentException. The compilation internally has a
// Dictionary<SyntaxTree, ...> that it uses to check if the SyntaxTree
// is applicable wheras the public interface requires us to enumerate
// the entire IEnumerable of trees in the Compilation.
if (!compilation.SyntaxTrees.Contains(declaringLocation.SyntaxTree))
{
continue;
}
var node = declaringLocation.GetSyntax();
if (node.Language == LanguageNames.VisualBasic)
{
......@@ -1027,7 +1047,7 @@ private void ParseArrayAndPointerTypes(List<ISymbol> symbols)
private void ConstructArray(List<ISymbol> symbols, int bounds)
{
for (int i = 0; i < symbols.Count; )
for (int i = 0; i < symbols.Count;)
{
var typeSymbol = symbols[i] as ITypeSymbol;
if (typeSymbol != null)
......@@ -1782,7 +1802,7 @@ private string ParseStringLiteral()
_index++;
var start = _index;
char ch;
char ch;
while ((ch = PeekNextChar()) != '\'' && ch != '\0')
{
_index++;
......
......@@ -427,6 +427,52 @@ public class C<S, T>
TestRoundTrip(constructed, compilation);
}
[Fact, WorkItem(11193, "https://github.com/dotnet/roslyn/issues/11193")]
public async Task TestGetInteriorSymbolsDoesNotCrashOnSpeculativeSemanticModel()
{
var markup = @"
class C
{
void foo()
{
System.Func<int> lambda = () =>
{
int x;
$$
}
}
}";
int position;
string text;
MarkupTestFile.GetPosition(markup, out text, out position);
var sourceText = SourceText.From(text);
var workspace = new AdhocWorkspace();
var project = workspace.AddProject("Test", LanguageNames.CSharp);
var document = workspace.AddDocument(project.Id, "testdocument", sourceText);
var firstModel = await document.GetSemanticModelAsync();
var tree1 = await document.GetSyntaxTreeAsync();
var basemethod1 = tree1.FindTokenOnLeftOfPosition(position, CancellationToken.None).GetAncestor<BaseMethodDeclarationSyntax>();
// Modify the document so we can use the old semantic model as a base.
var updated = sourceText.WithChanges(new TextChange(new TextSpan(position, 0), "insertion"));
workspace.TryApplyChanges(document.WithText(updated).Project.Solution);
document = workspace.CurrentSolution.GetDocument(document.Id);
var tree2 = await document.GetSyntaxTreeAsync();
var basemethod2 = tree2.FindTokenOnLeftOfPosition(position, CancellationToken.None).GetAncestor<BaseMethodDeclarationSyntax>();
var service = new CSharpSemanticFactsService();
SemanticModel testModel;
var m = service.TryGetSpeculativeSemanticModel(firstModel, basemethod1, basemethod2, out testModel);
var xSymbol = testModel.LookupSymbols(position).First(s => s.Name == "x");
// This should not throw an exception.
Assert.NotNull(SymbolId.CreateId(xSymbol));
}
private void TestRoundTrip(IEnumerable<ISymbol> symbols, Compilation compilation, Func<ISymbol, object> fnId = null)
{
foreach (var symbol in symbols)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册