You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.
We are using NRefactory for c# code completion and most times it works great :) Recently we found a problem which we think is caused by not finding the correct CSHarpTypeResolveContext. For a given code snippet and a given cursorPosition we calculate the CSHarpTypeResolveContext as follows (this is a simplified version of our production code):
publicclassTypeResolveContextDetermination{/// <summary>/// Resolves TypeResolveContext like this:/// (single) main-assembly -> current usingScope -> innermostTypeDefinition -> currentMember (e.g. Method, Ctor, etc.)/// </summary>/// <param name="sourceCode"></param>/// <param name="cursorIndex"></param>/// <returns></returns>publicCSharpTypeResolveContextDetermineTypeResolveContext(stringsourceCode,intcursorIndex){vardocument=newReadOnlyDocument(sourceCode);IProjectContentprojectContent;CSharpUnresolvedFileunresolvedFile;varcompilation=CreateCompilation(sourceCode,outprojectContent,outunresolvedFile);varcursorLocation=cursorIndex>0?document.GetLocation(cursorIndex):newTextLocation(1,1);vartypeResolveContext=newCSharpTypeResolveContext(compilation.MainAssembly);typeResolveContext=typeResolveContext.WithUsingScope(unresolvedFile.GetUsingScope(cursorLocation).Resolve(compilation));varcurrentTypeDefinition=unresolvedFile.GetInnermostTypeDefinition(cursorLocation);if(currentTypeDefinition!=null){varresolvedDef=currentTypeDefinition.Resolve(typeResolveContext).GetDefinition();typeResolveContext=typeResolveContext.WithCurrentTypeDefinition(resolvedDef);varcurMember=resolvedDef.Members.FirstOrDefault(m =>m.Region.Begin<=cursorLocation&&cursorLocation<m.BodyRegion.End);if(curMember!=null)// for testcase CodeB curMember is null, despite resolvedDef.Members contains MethodA (see tests at the bottom){typeResolveContext=typeResolveContext.WithCurrentMember(curMember);}}returntypeResolveContext;}privateICompilationCreateCompilation(stringsourceCode,outIProjectContentprojectContent,outCSharpUnresolvedFileunresolvedFile){projectContent=newCSharpProjectContent();projectContent=AddFileToProjectContent(projectContent,sourceCode,"FileOfInterest.cs",outunresolvedFile);projectContent.AddAssemblyReferences(newDefaultAssemblyReference(typeof(List<>).Assembly.GetName().Name));varcompilation=projectContent.CreateCompilation();returncompilation;}privateIProjectContentAddFileToProjectContent(IProjectContentprojectContent,stringsourceCode,stringfileName,outCSharpUnresolvedFileunresolvedFile){SyntaxTreesyntaxTree=newCSharpParser().Parse(sourceCode,fileName);syntaxTree.Freeze();unresolvedFile=syntaxTree.ToTypeSystem();returnprojectContent.AddOrUpdateFiles(unresolvedFile);}}
We think, the code above should satisfy the following four test cases. But for code snippet CodeB we can not determine the correct context.
namespaceNRefactoryTests{usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingICSharpCode.NRefactory;usingICSharpCode.NRefactory.CSharp;usingICSharpCode.NRefactory.CSharp.TypeSystem;usingICSharpCode.NRefactory.Editor;usingICSharpCode.NRefactory.TypeSystem;usingICSharpCode.NRefactory.TypeSystem.Implementation;usingNUnit.Framework;publicclassTypeContextTest{privateTypeResolveContextDeterminationtypeResolveContextDetermination;privateconststringCodeA=@"namespace TestNamespace{ public class TestClass { public virtual void MethodA() { TestClass test = new TestClass(); this.$$$ TestClass test2 = new TestClass(); } public virtual void MethodB() { } }}";privateconststringCodeB=@"namespace TestNamespace{ public class TestClass { public virtual void MethodA() { TestClass test = new TestClass(); this.M$$$ TestClass test2 = new TestClass(); } public virtual void MethodB() { } }}";privateconststringCodeC=@"namespace TestNamespace{ public class TestClass { public virtual void MethodA() { TestClass test = new TestClass(); this.M$$$ } public virtual void MethodB() { } }}";privateconststringCodeD=@"namespace TestNamespace{ public class TestClass { public virtual void MethodA() { this.M$$$ TestClass test2 = new TestClass(); } public virtual void MethodB() { } }}";[SetUp]publicvoidSetup(){typeResolveContextDetermination=newTypeResolveContextDetermination();}[Test]publicvoidResolveTypeContextWithNRefactory_ContextShouldBeMethodA([Values(CodeA,CodeB,CodeC,CodeD)]stringcode){intcursorPosition=code.IndexOf("$$$",StringComparison.Ordinal);code=code.Replace("$$$",string.Empty);varcontext=typeResolveContextDetermination.DetermineTypeResolveContext(code,cursorPosition);Assert.NotNull(context);Assert.NotNull(context.CurrentMember,"CurrentMember of the context should be MethodA");Assert.AreEqual("TestNamespace.TestClass.MethodA",context.CurrentMember.FullName,"CurrentMember of the context should be MethodA");}}
The problem with CodeB is, that we can not find a member:
Hi!
We are using NRefactory for c# code completion and most times it works great :) Recently we found a problem which we think is caused by not finding the correct
CSHarpTypeResolveContext
. For a given code snippet and a given cursorPosition we calculate theCSHarpTypeResolveContext
as follows (this is a simplified version of our production code):We think, the code above should satisfy the following four test cases. But for code snippet
CodeB
we can not determine the correct context.The problem with CodeB is, that we can not find a member:
Is this actually a bug or are we doing something wrong?
Thanks for your help!
The text was updated successfully, but these errors were encountered: