/*******************************************************************************
* Copyright (c) 2013, 2015 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.util.Collections;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.refactoring.includes.HeaderSubstitutionMap;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeMap;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
import org.eclipse.cdt.internal.ui.refactoring.includes.SymbolExportMap;
import junit.framework.Test;
/**
* Tests for {@link IncludeOrganizer}.
*/
public class IncludeOrganizerTest extends IncludesTestBase {
public IncludeOrganizerTest() {
super();
}
public IncludeOrganizerTest(String name) {
super(name);
}
public static Test suite() {
return suite(IncludeOrganizerTest.class);
}
@Override
protected void resetPreferences() {
super.resetPreferences();
IPreferenceStore preferenceStore = getPreferenceStore();
preferenceStore.setToDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
preferenceStore.setToDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
preferenceStore.setToDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
preferenceStore.setToDefault(PreferenceConstants.INCLUDES_HEADER_SUBSTITUTION);
preferenceStore.setToDefault(PreferenceConstants.INCLUDES_SYMBOL_EXPORTING_HEADERS);
}
private void assertExpectedResults() throws Exception {
String actual = organizeIncludes(ast.getOriginatingTranslationUnit());
assertEquals(selectedFile.getExpectedSource(), actual);
}
/**
* Invokes include organizer and returns the new contents of the translation unit.
*/
private String organizeIncludes(ITranslationUnit tu) throws Exception {
IHeaderChooser headerChooser = new FirstHeaderChooser();
IncludeOrganizer organizer = new IncludeOrganizer(tu, index, headerChooser);
MultiTextEdit edit = organizer.organizeIncludes(ast);
IDocument document = new Document(new String(tu.getContents()));
edit.apply(document);
return document.get();
}
//h1.h
//typedef int my_type;
//A.h
//class A {
// my_type m1();
//};
//A.cpp
//// Comment line 1
//// Comment line 2
//
//// Comment for m1
//my_type A::m1() {
// return 0;
//}
//====================
//// Comment line 1
//// Comment line 2
//
//#include "A.h"
//
//#include "h1.h"
//
//// Comment for m1
//my_type A::m1() {
// return 0;
//}
public void testNoExistingIncludes() throws Exception {
assertExpectedResults();
}
//B.h
//class B {};
//C.h
//class C {};
//A.h
//#if !defined(INCLUDE_GUARD)
//#define INCLUDE_GUARD
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A {
// B f;
// C m();
//};
//#endif // INCLUDE_GUARD
//====================
//#if !defined(INCLUDE_GUARD)
//#define INCLUDE_GUARD
//// Comment line 1
//// Comment line 2
//
//#include "B.h"
//
//class C;
//
//// Comment for A
//class A {
// B f;
// C m();
//};
//#endif // INCLUDE_GUARD
public void testIncludeGuards() throws Exception {
assertExpectedResults();
}
//B.h
//template <typename T> class B {};
//C.h
//class C {};
//A.h
//#pragma once
//namespace ns {
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A : public B<C> {};
//} // namespace ns
//====================
//#pragma once
//
//#include "B.h"
//#include "C.h"
//
//namespace ns {
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A : public B<C> {};
//} // namespace ns
public void testPragmaOnce() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int Type1;
//h2.h
//class Type2 {};
//h3.h
//enum Type3 { ONE, TWO };
//h4.h
//class Unrelated {};
//A.h
//#include "h1.h"
//class Type2;
//enum class Type3;
//extern Type1 f1();
//extern Type2 f2();
//extern Type3 f3();
//A.cpp
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
//====================
//// Comment
//
//#include "A.h"
//
//#include "h2.h" /* Required */ // another comment
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
public void testExistingIncludes() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int Type1;
//h2.h
//class Type2 {};
//h3.h
//enum class Type3 { ONE, TWO };
//h4.h
//class Unrelated {};
//A.h
//#include "h1.h"
//class Type2;
//enum class Type3;
//extern Type1 f1();
//extern Type2 f2();
//extern Type3 f3();
//A.cpp
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
//====================
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#include "A.h"
//
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
public void testExistingIncludesNoReordering() throws Exception {
getPreferenceStore().setValue(PreferenceConstants.INCLUDES_ALLOW_REORDERING, false);
assertExpectedResults();
}
//f.h
//void f(int p);
//f.cpp
//#include "f.h"
//void f(int p) {
//}
//====================
//#include "f.h"
//
//void f(int p) {
//}
public void testExistingPartnerIncludeIsNotRemoved() throws Exception {
IPreferenceStore preferenceStore = getPreferenceStore();
preferenceStore.setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true);
assertExpectedResults();
}
//a.h
//class A {};
//f.h
//#include "a.h"
//f.cpp
//#include "f.h"
//A a;
//====================
//#include "f.h"
//
//A a;
public void testPartnerInclusion() throws Exception {
assertExpectedResults();
}
//h1.h
//class A {};
//h2.h
//class B {};
//h3.h
//#include "h2.h" // IWYU pragma: export
//class C {};
//h4.h
//#include "h1.h"
///* IWYU pragma: begin_exports */
//#include "h3.h"
///* IWYU pragma: end_exports */
//class D {};
//source.cpp
//A a;
//B b;
//C c;
//D d;
//====================
//#include "h1.h"
//#include "h4.h"
//
//A a;
//B b;
//C c;
//D d;
public void testHeaderExport() throws Exception {
assertExpectedResults();
}
//dir1/private1.h
///** @file dir1/private1.h
// * This is an internal header file, included by other library headers.
// * Do not attempt to use it directly. @headername{dir1/public1.h}
// */
//class A {};
//dir1/public1.h
//#include "private1.h"
//dir1/private2.h
//// IWYU pragma: private,
//// include "dir1/public2.h"
//class B {};
//dir1/public2.h
//#include "private2.h"
//dir1/private3.h
//// IWYU pragma: private
//class C {};
//dir1/public3.h
//#include "private3.h"
//dir2/private4.h
//// IWYU pragma: private, include "dir2/public4.h"
//class D {};
//dir2/public4.h
//#include "private4.h"
//dir2/source.cpp
//A a;
//B b;
//C c;
//D d;
//====================
//#include "dir1/public1.h"
//#include "dir1/public2.h"
//#include "dir1/public3.h"
//#include "dir2/private4.h"
//
//A a;
//B b;
//C c;
//D d;
public void testPrivateHeaders() throws Exception {
assertExpectedResults();
}
//h1.h
//class A {};
//h2.h
//#include "h1.h" // IWYU pragma: export
//class B {};
//h3.h
//#include "h2.h"
//source.cpp
//A a;
//B b;
//====================
//#include "h3.h"
//
//A a;
//B b;
public void testIndirectHeaderExport() throws Exception {
HeaderSubstitutionMap headerMap = new HeaderSubstitutionMap("Test", false,
new IncludeMap(true, new String[] { "h2.h", "h3.h"}),
new IncludeMap(false));
getPreferenceStore().setValue(PreferenceConstants.INCLUDES_HEADER_SUBSTITUTION,
HeaderSubstitutionMap.serializeMaps(Collections.singletonList(headerMap)));
assertExpectedResults();
}
//h1.h
//h2.h
//h3.h
//source.cpp
//#include "h1.h"
//#include "h2.h" // IWYU pragma: keep
//#include "h3.h" /* IWYU pragma: keep */
//====================
//#include "h2.h" // IWYU pragma: keep
//#include "h3.h" /* IWYU pragma: keep */
public void testPragmaKeep() throws Exception {
assertExpectedResults();
}
//h1.h
//#define M2(t, p) t p
//h2.h
//#include "h1.h"
//#define M1(x, y) M2(int, x) = y
//h3.h
//#include "h2.h"
//source.cpp
//#include "h3.h"
//M1(a, 1);
//====================
//#include "h2.h"
//
//M1(a, 1);
public void testMacro() throws Exception {
IPreferenceStore preferenceStore = getPreferenceStore();
assertExpectedResults();
}
//string.h
//#include "stddef.h"
//extern char* strchr(char* s, int c);
//stddef.h
//#define NULL 0
//source.cpp
//#include "stddef.h"
//char* test() {
// int* p = NULL;
// return strchr("aaa", '*');
//}
//====================
//#include "string.h"
//
//char* test() {
// int* p = NULL;
// return strchr("aaa", '*');
//}
public void testExportedSymbol() throws Exception {
IPreferenceStore preferenceStore = getPreferenceStore();
SymbolExportMap symbolExportMap = new SymbolExportMap(new String[] { "NULL", "string.h" });
preferenceStore.setValue(PreferenceConstants.INCLUDES_SYMBOL_EXPORTING_HEADERS,
SymbolExportMap.serializeMaps(Collections.singletonList(symbolExportMap)));
assertExpectedResults();
}
//h1.h
//class A {};
//class B;
//h2.h
//class C {};
//source.cpp
//#include "h2.h"
//A a;
//B* b;
//C* c;
//====================
//#include "h1.h"
//
//class C;
//
//A a;
//B* b;
//C* c;
public void testSymbolToDeclareIsDefinedInIncludedHeader() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int int32;
//h2.h
//#include "h1.h"
//extern int32 var;
//source.cpp
//int a = var;
//====================
//#include "h2.h"
//
//int a = var;
public void testVariableReference() throws Exception {
assertExpectedResults();
}
//h1.h
//struct A {
// template <typename T>
// void m(const T& p);
//};
//h2.h
//#include "h1.h"
//template<typename T>
//void A::m(const T& p) {
//}
//h3.h
//#include "h1.h"
//typedef A B;
//source.cpp
//void test(B& b) {
// b.m(1);
//}
//====================
//#include "h2.h"
//#include "h3.h"
//
//void test(B& b) {
// b.m(1);
//}
public void testMethodDefinedInHeader() throws Exception {
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
//struct A {
// void operator()();
//};
//struct B : public A {
//};
//h2.h
//#include "h1.h"
//
//struct C {
// B b;
//};
//source.cpp
//void test(C* c) {
// c->b();
//}
//====================
//#include "h2.h"
//
//void test(C* c) {
// c->b();
//}
public void testFieldAccess_442841() throws Exception {
assertExpectedResults();
}
//h1.h
//namespace ns3 {
//class C {};
//namespace ns2 {
//class A {};
//class B {};
//namespace ns1 {
//C* f(const A& a, B* b);
//} // ns1
//} // ns2
//} // ns3
//source.cpp
//#include "h1.h"
//void test(ns3::ns2::A& a) {
// ns3::C* c = ns3::ns2::ns1::f(a, nullptr);
//}
//====================
//namespace ns3 {
//class C;
//namespace ns2 {
//class A;
//class B;
//} /* namespace ns2 */
//} /* namespace ns3 */
//namespace ns3 {
//namespace ns2 {
//namespace ns1 {
//C * f(const A &a, B *b);
//} /* namespace ns1 */
//} /* namespace ns2 */
//} /* namespace ns3 */
//
//void test(ns3::ns2::A& a) {
// ns3::C* c = ns3::ns2::ns1::f(a, nullptr);
//}
public void testForwardDeclarations() throws Exception {
// TODO(sprigogin): Move ns1 outside of other namespaces after IncludeOrganizer starts using ASTWriter.
IPreferenceStore preferenceStore = getPreferenceStore();
preferenceStore.setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true);
assertExpectedResults();
}
}