1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-21 07:55:24 +02:00

Bug 488349 - Organize Includes removes an include necessary for a method

call

Change-Id: I309046e32ea2be5f0b6ecc00643d03c131bfafb6
This commit is contained in:
Sergey Prigogin 2016-02-24 20:49:27 -08:00
parent 5d40605a40
commit 01b0b877e1
4 changed files with 70 additions and 13 deletions

View file

@ -201,6 +201,23 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
assertDeclared(); assertDeclared();
} }
// struct A {
// void a() const;
// };
// struct B : public A {
// }
// struct C {
// const B& c() const;
// };
// void test(const C& x) {
// x.c().a();
// }
public void testMethodCall_488349() throws Exception {
assertDefined("A::a", "B", "C", "C::c");
assertDeclared();
}
// class Base { // class Base {
// public: // public:
// void m(); // void m();

View file

@ -12,8 +12,6 @@ package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.util.Collections; import java.util.Collections;
import junit.framework.Test;
import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.Document; import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocument;
@ -29,6 +27,8 @@ import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition; import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition;
import org.eclipse.cdt.internal.ui.refactoring.includes.SymbolExportMap; import org.eclipse.cdt.internal.ui.refactoring.includes.SymbolExportMap;
import junit.framework.Test;
/** /**
* Tests for {@link IncludeOrganizer}. * Tests for {@link IncludeOrganizer}.
*/ */
@ -571,6 +571,38 @@ public class IncludeOrganizerTest extends IncludesTestBase {
assertExpectedResults(); assertExpectedResults();
} }
//a.h
//struct A {
// void a() const;
//};
//b.h
//#include "a.h"
//struct B : public A {
//}
//c.h
//class B;
//
//struct C {
// const B& c() const;
//};
//source.cpp
//void test(const C& x) {
// x.c().a();
//}
//====================
//#include "b.h"
//#include "c.h"
//
//void test(const C& x) {
// x.c().a();
//}
public void testMethodCall_488349() throws Exception {
assertExpectedResults();
}
//h1.h //h1.h
//struct A { //struct A {
// void operator()(); // void operator()();

View file

@ -701,8 +701,9 @@ public class BindingClassifier {
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
IASTInitializerClause[] arguments = functionCallExpression.getArguments(); IASTInitializerClause[] arguments = functionCallExpression.getArguments();
IBinding binding = getBindingOfExpression(functionNameExpression); IASTName functionName = getNameOfIdOrFieldReferenceExpression(functionNameExpression);
if (binding != null) { if (functionName != null) {
IBinding binding = functionName.resolveBinding();
if (binding instanceof IProblemBinding) { if (binding instanceof IProblemBinding) {
IBinding[] candidates = ((IProblemBinding) binding).getCandidateBindings(); IBinding[] candidates = ((IProblemBinding) binding).getCandidateBindings();
if (candidates.length != 0) { if (candidates.length != 0) {
@ -713,13 +714,18 @@ public class BindingClassifier {
defineBinding(binding); defineBinding(binding);
} }
} else { } else {
LookupData data = new LookupData(functionName);
IType impliedObjectType = data.getImpliedObjectType();
if (impliedObjectType != null)
defineTypeExceptTypedefOrNonFixedEnum(impliedObjectType);
defineBindingForFunctionCall(binding, arguments); defineBindingForFunctionCall(binding, arguments);
} }
} }
if (functionCallExpression instanceof IASTImplicitNameOwner) { if (functionCallExpression instanceof IASTImplicitNameOwner) {
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) functionCallExpression).getImplicitNames(); IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) functionCallExpression).getImplicitNames();
for (IASTName name : implicitNames) { for (IASTName name : implicitNames) {
binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
if (binding instanceof IFunction) { if (binding instanceof IFunction) {
defineForFunctionCall((IFunction) binding, arguments); defineForFunctionCall((IFunction) binding, arguments);
} }
@ -739,8 +745,9 @@ public class BindingClassifier {
IASTExpression fieldOwner = ((IASTFieldReference) expression).getFieldOwner(); IASTExpression fieldOwner = ((IASTFieldReference) expression).getFieldOwner();
IType expressionType = fieldOwner.getExpressionType(); IType expressionType = fieldOwner.getExpressionType();
defineIndirectTypes(expressionType); defineIndirectTypes(expressionType);
IBinding binding = getBindingOfExpression(fieldOwner); IASTName name = getNameOfIdOrFieldReferenceExpression(fieldOwner);
if (binding != null) { if (name != null) {
IBinding binding = name.resolveBinding();
defineTypeForBinding(binding, expressionType); defineTypeForBinding(binding, expressionType);
} }
} else if (expression instanceof ICPPASTNewExpression) { } else if (expression instanceof ICPPASTNewExpression) {
@ -1422,13 +1429,13 @@ public class BindingClassifier {
} }
/** /**
* @return the binding corresponding to the ID or the field reference expression. * Returns the name corresponding to the ID or the field reference expression.
*/ */
private static IBinding getBindingOfExpression(IASTExpression expression) { private static IASTName getNameOfIdOrFieldReferenceExpression(IASTExpression expression) {
if (expression instanceof IASTIdExpression) { if (expression instanceof IASTIdExpression) {
return ((IASTIdExpression) expression).getName().resolveBinding(); return ((IASTIdExpression) expression).getName();
} else if (expression instanceof IASTFieldReference) { } else if (expression instanceof IASTFieldReference) {
return ((IASTFieldReference) expression).getFieldName().resolveBinding(); return ((IASTFieldReference) expression).getFieldName();
} }
return null; return null;
} }

View file

@ -836,8 +836,9 @@ public class IncludeOrganizer {
indexNames = index.findDeclarations(binding); indexNames = index.findDeclarations(binding);
} else if (binding instanceof ICPPMethod) { } else if (binding instanceof ICPPMethod) {
// Include the headers containing method definitions except the ones also containing // Include the headers containing method definitions except the ones also containing
// the definition of the owner class. The headers defining the owner class are taken // the definition of the owner class. The definition of owner class will be included because
// care of separately. // BindingClassifier must add a binding that is either the owner itself, or its subclass, or
// a typedef pointing to it.
Set<IIndexFile> declarationFiles = new HashSet<>(); Set<IIndexFile> declarationFiles = new HashSet<>();
IIndexName[] declarations = index.findNames(binding, IIndex.FIND_DECLARATIONS); IIndexName[] declarations = index.findNames(binding, IIndex.FIND_DECLARATIONS);
for (IIndexName declaration : declarations) { for (IIndexName declaration : declarations) {