Browse Source

Fixed SD2-797: Code-completion for nested classes is broken

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1379 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
16d87fd62e
  1. 2
      data/templates/file/CSharp/CSharp.Web.WebControl.xft
  2. 2
      data/templates/file/CSharp/CSharp.Web.WebService.xft
  3. 9
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs
  4. 18
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs
  5. 21
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
  6. 92
      src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs
  7. 13
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs
  8. 4
      src/Main/Base/Project/Src/Dom/ResolveResult.cs
  9. 14
      src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs
  10. 7
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
  11. 23
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  12. 15
      src/Main/Base/Test/InnerClassesResolverTests.cs

2
data/templates/file/CSharp/CSharp.Web.WebControl.xft

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
icon = "C#.File.NewClass"
category = "C#"
subcategory = "ASP.NET"
defaultname = "WebControl"
defaultname = "WebControl${Number}"
language = "C#"
/>

2
data/templates/file/CSharp/CSharp.Web.WebService.xft

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
icon = "C#.File.NewClass"
category = "C#"
subcategory = "ASP.NET"
defaultname = "WebService.asmx"
defaultname = "WebService${Number}.asmx"
language = "C#"
/>

9
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs

@ -109,5 +109,14 @@ namespace Grunwald.BooBinding @@ -109,5 +109,14 @@ namespace Grunwald.BooBinding
return GetProperty("Ducky", false);
}
}
public override void SetProperty<T>(string configurationName, string platform, string property, T value, PropertyStorageLocations location)
{
bool oldDucky = Ducky;
base.SetProperty(configurationName, platform, property, value, location);
if (Ducky != oldDucky) {
ParserService.Reparse(this);
}
}
}
}

18
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs

@ -213,17 +213,23 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -213,17 +213,23 @@ namespace Grunwald.BooBinding.CodeCompletion
return CreateReturnType(reference, c, method, c.Region.BeginLine + 1, 1, _cu.ProjectContent);
}
}
internal static IReturnType GetDefaultReturnType(IProjectContent projectContent)
{
BooProject project = projectContent.Project as BooProject;
if (project != null && project.Ducky)
return new BooResolver.DuckClass(new DefaultCompilationUnit(projectContent)).DefaultReturnType;
else
return ReflectionReturnType.Object;
}
public static IReturnType CreateReturnType(AST.TypeReference reference, IClass callingClass,
IMethodOrProperty callingMember, int caretLine, int caretColumn,
IProjectContent projectContent)
{
System.Diagnostics.Debug.Assert(projectContent != null);
if (reference == null) {
BooProject project = projectContent.Project as BooProject;
if (project != null && project.Ducky)
return new BooResolver.DuckClass(new DefaultCompilationUnit(projectContent)).DefaultReturnType;
else
return ReflectionReturnType.Object;
return GetDefaultReturnType(projectContent);
}
if (reference is AST.ArrayTypeReference) {
AST.ArrayTypeReference arr = (AST.ArrayTypeReference)reference;
@ -278,7 +284,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -278,7 +284,7 @@ namespace Grunwald.BooBinding.CodeCompletion
if (field.Initializer != null)
return new InferredReturnType(field.Initializer, OuterClass);
else
return ReflectionReturnType.Object;
return GetDefaultReturnType(_cu.ProjectContent);
} else {
return CreateReturnType(field.Type);
}

21
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs

@ -168,9 +168,14 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -168,9 +168,14 @@ namespace Grunwald.BooBinding.CodeCompletion
}
}
}
if (callingClass != null) {
if (ResolveMember(callingClass.DefaultReturnType, identifier))
return true;
{ // Find members of this class or enclosing classes
IClass tmp = callingClass;
while (tmp != null) {
if (ResolveMember(tmp.DefaultReturnType, identifier))
return true;
tmp = tmp.DeclaringType;
}
}
string namespaceName = projectContent.SearchNamespace(identifier, callingClass, cu, resolver.CaretLine, resolver.CaretColumn);
@ -294,10 +299,12 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -294,10 +299,12 @@ namespace Grunwald.BooBinding.CodeCompletion
if (resolveResult is TypeResolveResult) {
IClass rClass = (resolveResult as TypeResolveResult).ResolvedClass;
if (rClass != null) {
foreach (IClass innerClass in rClass.InnerClasses) {
if (IsSameName(innerClass.Name, node.Name)) {
MakeTypeResult(innerClass);
return;
foreach (IClass baseClass in rClass.ClassInheritanceTree) {
foreach (IClass innerClass in baseClass.InnerClasses) {
if (IsSameName(innerClass.Name, node.Name)) {
MakeTypeResult(innerClass);
return;
}
}
}
}

92
src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs

@ -29,16 +29,6 @@ namespace Grunwald.BooBinding.Tests @@ -29,16 +29,6 @@ namespace Grunwald.BooBinding.Tests
return Resolve<T>(normalProg, code, marker);
}
T ResolveReg<T>(string code) where T : ResolveResult
{
return ResolveReg<T>(code, "/*1*/");
}
T ResolveReg<T>(string code, string marker) where T : ResolveResult
{
return Resolve<T>(regressionProg, code, marker);
}
T Resolve<T>(string prog, string code, string marker) where T : ResolveResult
{
ResolveResult rr = Resolve(prog, new ExpressionResult(code), marker);
@ -55,10 +45,12 @@ namespace Grunwald.BooBinding.Tests @@ -55,10 +45,12 @@ namespace Grunwald.BooBinding.Tests
}
const string fileName = "tempFile.boo";
DefaultProjectContent lastPC;
void Register(string prog)
{
DefaultProjectContent pc = new DefaultProjectContent();
lastPC = pc;
ParserService.ForceProjectContent(pc);
pc.ReferencedContents.Add(ProjectContentRegistry.Mscorlib);
pc.ReferencedContents.Add(ProjectContentRegistry.WinForms);
@ -230,16 +222,16 @@ namespace Grunwald.BooBinding.Tests @@ -230,16 +222,16 @@ namespace Grunwald.BooBinding.Tests
[Test]
public void Boo629VariableScope()
{
LocalResolveResult rr = ResolveReg<LocalResolveResult>("boo629");
LocalResolveResult rr = Resolve<LocalResolveResult>(regressionProg, "boo629", "/*1*/");
Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName);
}
[Test]
public void Boo640ConditionalAssignment()
{
LocalResolveResult rr = ResolveReg<LocalResolveResult>("boo640b");
LocalResolveResult rr = Resolve<LocalResolveResult>(regressionProg, "boo640b", "/*1*/");
Assert.AreEqual("System.Reflection.FieldInfo", rr.ResolvedType.FullyQualifiedName);
rr = ResolveReg<LocalResolveResult>("boo640a", "/*640*/");
rr = Resolve<LocalResolveResult>(regressionProg, "boo640a", "/*640*/");
Assert.AreEqual("System.Object", rr.ResolvedType.FullyQualifiedName);
Assert.IsNull(Resolve(regressionProg, new ExpressionResult("boo640a"), "/*1*/"));
}
@ -264,6 +256,80 @@ namespace Grunwald.BooBinding.Tests @@ -264,6 +256,80 @@ namespace Grunwald.BooBinding.Tests
}
#endregion
#region Nested Classes
const string nestedClassProg =
"class Outer:\n" +
"\tpublic static outerField = 1\n" +
"\tpublic class Inner:\n/*inner*/" +
"\t\tpublic innerField = 2\n" +
"class Derived(Outer):\n/*derived*/" +
"\tpublic static derivedField = 3\n" +
"def Method():\n" +
"\ti as Outer.Inner\n" +
"\ti2 as Derived.Inner\n" +
"\t/*1*/";
[Test]
public void NestedClassTypeResolution()
{
TypeResolveResult trr;
trr = Resolve<TypeResolveResult>(nestedClassProg, "Outer.Inner", "/*1*/");
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
trr = Resolve<TypeResolveResult>(nestedClassProg, "Inner", "/*inner*/");
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
trr = Resolve<TypeResolveResult>(nestedClassProg, "Inner", "/*derived*/");
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
trr = Resolve<TypeResolveResult>(nestedClassProg, "Derived.Inner", "/*1*/");
Assert.AreEqual("Outer.Inner", trr.ResolvedClass.FullyQualifiedName);
}
[Test]
public void NestedClassCtrlSpace()
{
CtrlSpace(nestedClassProg.Replace("/*inner*/", "/*mark*/"), "outerField", "innerField", "Inner", "Outer", "Derived");
CtrlSpace(nestedClassProg.Replace("/*derived*/", "/*mark*/"), "outerField", "derivedField", "Inner", "Outer", "Derived");
}
[Test]
public void NestedClassParentStaticField()
{
MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "outerField", "/*inner*/");
Assert.AreEqual("Outer.outerField", mrr.ResolvedMember.FullyQualifiedName);
}
[Test]
public void NestedClassCC()
{
LocalResolveResult rr = Resolve<LocalResolveResult>(nestedClassProg, "i", "/*1*/");
Assert.AreEqual("Outer.Inner", rr.ResolvedType.FullyQualifiedName);
bool ok = false;
foreach (object o in rr.GetCompletionData(lastPC)) {
IMember m = o as IMember;
if (m != null && m.Name == "innerField")
ok = true;
}
Assert.IsTrue(ok);
MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "i.innerField", "/*1*/");
Assert.AreEqual("Outer.Inner.innerField", mrr.ResolvedMember.FullyQualifiedName);
}
[Test]
public void NestedClassCC2()
{
LocalResolveResult rr = Resolve<LocalResolveResult>(nestedClassProg, "i2", "/*1*/");
Assert.AreEqual("Outer.Inner", rr.ResolvedType.FullyQualifiedName);
bool ok = false;
foreach (object o in rr.GetCompletionData(lastPC)) {
IMember m = o as IMember;
if (m != null && m.Name == "innerField")
ok = true;
}
Assert.IsTrue(ok);
MemberResolveResult mrr = Resolve<MemberResolveResult>(nestedClassProg, "i2.innerField", "/*1*/");
Assert.AreEqual("Outer.Inner.innerField", mrr.ResolvedMember.FullyQualifiedName);
}
#endregion
#region CtrlSpace
void CtrlSpace(string prog, params string[] expected)
{

13
src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs

@ -447,11 +447,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -447,11 +447,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return CreateMemberResolveResult(member);
c = type.GetUnderlyingClass();
if (c != null) {
List<IClass> innerClasses = c.InnerClasses;
if (innerClasses != null) {
foreach (IClass innerClass in innerClasses) {
if (IsSameName(innerClass.Name, fieldReferenceExpression.FieldName)) {
return new TypeResolveResult(callingClass, callingMember, innerClass);
foreach (IClass baseClass in c.ClassInheritanceTree) {
List<IClass> innerClasses = baseClass.InnerClasses;
if (innerClasses != null) {
foreach (IClass innerClass in innerClasses) {
if (IsSameName(innerClass.Name, fieldReferenceExpression.FieldName)) {
return new TypeResolveResult(callingClass, callingMember, innerClass);
}
}
}
}
@ -1051,7 +1053,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -1051,7 +1053,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
members.Clear();
IClass c = callingClass.DeclaringType;
while (c != null) {
result.Add(c);
t = c.DefaultReturnType;
members.AddRange(t.GetMethods());
members.AddRange(t.GetFields());

4
src/Main/Base/Project/Src/Dom/ResolveResult.cs

@ -430,7 +430,9 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -430,7 +430,9 @@ namespace ICSharpCode.SharpDevelop.Dom
{
ArrayList ar = GetCompletionData(projectContent.Language, true);
if (resolvedClass != null) {
ar.AddRange(resolvedClass.InnerClasses);
foreach (IClass baseClass in resolvedClass.ClassInheritanceTree) {
ar.AddRange(baseClass.InnerClasses);
}
}
return ar;
}

14
src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs

@ -565,12 +565,14 @@ namespace ICSharpCode.Core @@ -565,12 +565,14 @@ namespace ICSharpCode.Core
string outerName = typeName.Substring(0, lastIndex);
IClass upperClass = GetClassInternal(outerName, typeParameterCount, language);
if (upperClass != null) {
List<IClass> innerClasses = upperClass.InnerClasses;
if (innerClasses != null) {
string innerName = typeName.Substring(lastIndex + 1);
foreach (IClass innerClass in innerClasses) {
if (language.NameComparer.Equals(innerClass.Name, innerName)) {
return innerClass;
foreach (IClass upperBaseClass in upperClass.ClassInheritanceTree) {
List<IClass> innerClasses = upperBaseClass.InnerClasses;
if (innerClasses != null) {
string innerName = typeName.Substring(lastIndex + 1);
foreach (IClass innerClass in innerClasses) {
if (language.NameComparer.Equals(innerClass.Name, innerName)) {
return innerClass;
}
}
}
}

7
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -177,6 +177,13 @@ namespace ICSharpCode.Core @@ -177,6 +177,13 @@ namespace ICSharpCode.Core
return project.Items.Count;
}
internal void ReInitialize2()
{
if (initializing) return;
initializing = true;
Initialize2();
}
internal void Initialize2()
{
if (!initializing) return;

23
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -182,10 +182,27 @@ namespace ICSharpCode.Core @@ -182,10 +182,27 @@ namespace ICSharpCode.Core
{
ParseProjectContent newContent = (ParseProjectContent)state;
newContent.Initialize1();
StatusBarService.ProgressMonitor.BeginTask("Parsing...", newContent.GetInitializationWorkAmount());
newContent.Initialize2();
StatusBarService.ProgressMonitor.Done();
}
static void ReparseProject(object state)
{
ParseProjectContent newContent = (ParseProjectContent)state;
StatusBarService.ProgressMonitor.BeginTask("Parsing...", newContent.GetInitializationWorkAmount());
newContent.ReInitialize2();
StatusBarService.ProgressMonitor.Done();
}
public static void Reparse(IProject project)
{
ParseProjectContent pc = GetProjectContent(project) as ParseProjectContent;
if (pc != null) {
ThreadPool.QueueUserWorkItem(ReparseProject, pc);
}
}
internal static IProjectContent CreateProjectContentForAddedProject(IProject project)
{
lock (projectContents) {
@ -198,8 +215,10 @@ namespace ICSharpCode.Core @@ -198,8 +215,10 @@ namespace ICSharpCode.Core
public static IProjectContent GetProjectContent(IProject project)
{
if (projectContents.ContainsKey(project)) {
return projectContents[project];
lock (projectContents) {
if (projectContents.ContainsKey(project)) {
return projectContents[project];
}
}
return null;
}

15
src/Main/Base/Test/InnerClassesResolverTests.cs

@ -106,6 +106,21 @@ class C : A { @@ -106,6 +106,21 @@ class C : A {
ResolveResult result = Resolve(program, "B", 6);
Assert.IsTrue(result is TypeResolveResult);
Assert.AreEqual("A.B", result.ResolvedType.FullyQualifiedName);
result = Resolve(program, "C.B", 6);
Assert.IsTrue(result is TypeResolveResult);
Assert.AreEqual("A.B", result.ResolvedType.FullyQualifiedName);
result = Resolve(program, "C", 6);
Assert.IsTrue(result is TypeResolveResult);
Assert.AreEqual("C", result.ResolvedType.FullyQualifiedName);
foreach (object o in result.GetCompletionData(nrrt.lastPC)) {
if (o is IClass) {
Assert.AreEqual("A.B", ((IClass)o).FullyQualifiedName);
return;
}
}
Assert.Fail("Inherited inner class not visible.");
}
}
}

Loading…
Cancel
Save