mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 00:45:28 +02:00
Bug 414838 - New class creation doesn't properly handle include path
with directories for non-system headers.
This commit is contained in:
parent
1524122c03
commit
eca8e6004c
19 changed files with 497 additions and 418 deletions
|
@ -36,7 +36,7 @@ import org.eclipse.cdt.ui.PreferenceConstants;
|
|||
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.BindingClassifier;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.InclusionContext;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeCreationContext;
|
||||
|
||||
/**
|
||||
* Tests for {@link BindingClassifier}.
|
||||
|
@ -68,7 +68,7 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
|||
if (fBindingClassifier == null) {
|
||||
IASTTranslationUnit ast = getAst();
|
||||
ITranslationUnit tu = ast.getOriginatingTranslationUnit();
|
||||
InclusionContext context = new InclusionContext(tu, fIndex);
|
||||
IncludeCreationContext context = new IncludeCreationContext(tu, fIndex);
|
||||
fBindingClassifier = new BindingClassifier(context);
|
||||
fBindingClassifier.classifyNodeContents(ast);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.eclipse.cdt.core.model.ISourceReference;
|
|||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeInfo;
|
||||
|
||||
/**
|
||||
* Adds includes and 'using' declarations to a translation unit.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Contributors:
|
||||
* Sergey Prigogin (Google) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.refactoring.includes;
|
||||
package org.eclipse.cdt.internal.corext.codemanipulation;
|
||||
|
||||
import com.ibm.icu.text.Collator;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2013 Google, Inc and others.
|
||||
* Copyright (c) 2013 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
|
||||
|
@ -8,24 +8,17 @@
|
|||
* Contributors:
|
||||
* Sergey Prigogin (Google) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.refactoring.includes;
|
||||
package org.eclipse.cdt.internal.corext.codemanipulation;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexInclude;
|
||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||
|
@ -34,65 +27,51 @@ import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor;
|
|||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPath;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPathElement;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.ScannerUtility;
|
||||
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences;
|
||||
|
||||
/**
|
||||
* Context for managing include statements.
|
||||
*/
|
||||
public class InclusionContext {
|
||||
private static final IPath UNRESOLVED_INCLUDE = Path.EMPTY;
|
||||
|
||||
private final ITranslationUnit fTu;
|
||||
private final IProject fProject;
|
||||
private final IPath fCurrentDirectory;
|
||||
private final IncludePreferences fPreferences;
|
||||
private final IncludeSearchPath fIncludeSearchPath;
|
||||
private final Map<IncludeInfo, IPath> fIncludeResolutionCache;
|
||||
private final Map<IPath, IncludeInfo> fInverseIncludeResolutionCache;
|
||||
private final IIndex fIndex;
|
||||
private final Set<IPath> fHeadersToInclude;
|
||||
private final Set<IPath> fHeadersAlreadyIncluded;
|
||||
private final Set<IPath> fHeadersIncludedPreviously;
|
||||
private final IncludePreferences fPreferences;
|
||||
|
||||
public InclusionContext(ITranslationUnit tu, IIndex index) {
|
||||
public InclusionContext(ITranslationUnit tu) {
|
||||
fTu = tu;
|
||||
fIndex = index;
|
||||
ICProject cProject = fTu.getCProject();
|
||||
fPreferences = new IncludePreferences(cProject);
|
||||
fProject = cProject.getProject();
|
||||
fCurrentDirectory = fTu.getResource().getParent().getLocation();
|
||||
IScannerInfo scannerInfo = fTu.getScannerInfo(true);
|
||||
fIncludeSearchPath = CPreprocessor.configureIncludeSearchPath(fCurrentDirectory.toFile(), scannerInfo);
|
||||
fIncludeResolutionCache = new HashMap<IncludeInfo, IPath>();
|
||||
fInverseIncludeResolutionCache = new HashMap<IPath, IncludeInfo>();
|
||||
fHeadersToInclude = new HashSet<IPath>();
|
||||
fHeadersAlreadyIncluded = new HashSet<IPath>();
|
||||
fHeadersIncludedPreviously = new HashSet<IPath>();
|
||||
fPreferences = new IncludePreferences(cProject);
|
||||
}
|
||||
|
||||
public ITranslationUnit getTranslationUnit() {
|
||||
public final ITranslationUnit getTranslationUnit() {
|
||||
return fTu;
|
||||
}
|
||||
|
||||
public IIndex getIndex() {
|
||||
return fIndex;
|
||||
public final IProject getProject() {
|
||||
return fProject;
|
||||
}
|
||||
|
||||
public IProject getProject() {
|
||||
return fProject;
|
||||
public final IPath getCurrentDirectory() {
|
||||
return fCurrentDirectory;
|
||||
}
|
||||
|
||||
public IncludePreferences getPreferences() {
|
||||
return fPreferences;
|
||||
}
|
||||
|
||||
public boolean isCXXLanguage() {
|
||||
return fTu.isCXXLanguage();
|
||||
}
|
||||
|
||||
public IPath getCurrentDirectory() {
|
||||
return fCurrentDirectory;
|
||||
}
|
||||
|
||||
public IPath resolveInclude(IncludeInfo include) {
|
||||
IPath path = fIncludeResolutionCache.get(include);
|
||||
if (path == null) {
|
||||
|
@ -161,82 +140,89 @@ public class InclusionContext {
|
|||
return include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes headers that are exported by other headers that will be included
|
||||
*/
|
||||
public void removeExportedHeaders() throws CoreException {
|
||||
// Index files keyed by their absolute paths.
|
||||
Map<IPath, IIndexFile> filesByPath = new HashMap<IPath, IIndexFile>();
|
||||
for (IIndexFile file : fIndex.getAllFiles()) {
|
||||
IPath path = getPath(file);
|
||||
filesByPath.put(path, file);
|
||||
}
|
||||
|
||||
Set<IPath> exportedHeaders = new HashSet<IPath>();
|
||||
for (IPath path : fHeadersToInclude) {
|
||||
if (!exportedHeaders.contains(path)) {
|
||||
IIndexFile file = filesByPath.get(path);
|
||||
if (file != null) { // file can be null if the header was not indexed.
|
||||
ArrayDeque<IIndexFile> queue = new ArrayDeque<IIndexFile>();
|
||||
queue.add(file);
|
||||
while ((file = queue.pollFirst()) != null) {
|
||||
for (IIndexInclude include : file.getIncludes()) {
|
||||
if (fPreferences.allowIndirectInclusion || include.isIncludedFileExported()) {
|
||||
file = fIndex.resolveInclude(include);
|
||||
if (file != null) {
|
||||
if (exportedHeaders.add(getPath(file)))
|
||||
queue.add(file);
|
||||
}
|
||||
}
|
||||
public IncludeGroupStyle getIncludeStyle(IPath headerPath) {
|
||||
IncludeKind includeKind;
|
||||
IncludeInfo includeInfo = getIncludeForHeaderFile(headerPath);
|
||||
if (includeInfo != null && includeInfo.isSystem()) {
|
||||
if (headerPath.getFileExtension() == null) {
|
||||
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
||||
} else {
|
||||
includeKind = IncludeKind.SYSTEM_WITH_EXTENSION;
|
||||
}
|
||||
} else if (isPartnerFile(headerPath)) {
|
||||
includeKind = IncludeKind.PARTNER;
|
||||
} else {
|
||||
IPath dir = getCurrentDirectory();
|
||||
if (dir.isPrefixOf(headerPath)) {
|
||||
if (headerPath.segmentCount() == dir.segmentCount() + 1) {
|
||||
includeKind = IncludeKind.IN_SAME_FOLDER;
|
||||
} else {
|
||||
includeKind = IncludeKind.IN_SUBFOLDER;
|
||||
}
|
||||
} else {
|
||||
IFile[] files = ResourceLookup.findFilesForLocation(headerPath);
|
||||
if (files.length == 0) {
|
||||
includeKind = IncludeKind.EXTERNAL;
|
||||
} else {
|
||||
IProject project = getProject();
|
||||
includeKind = IncludeKind.IN_OTHER_PROJECT;
|
||||
for (IFile file : files) {
|
||||
if (file.getProject().equals(project)) {
|
||||
includeKind = IncludeKind.IN_SAME_PROJECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fHeadersToInclude.removeAll(exportedHeaders);
|
||||
}
|
||||
|
||||
private static IPath getPath(IIndexFile file) throws CoreException {
|
||||
return IndexLocationFactory.getAbsolutePath(file.getLocation());
|
||||
return fPreferences.includeStyles.get(includeKind);
|
||||
}
|
||||
|
||||
|
||||
public IncludeGroupStyle getIncludeStyle(IncludeInfo includeInfo) {
|
||||
IncludeKind includeKind;
|
||||
IPath path = Path.fromPortableString(includeInfo.getName());
|
||||
if (includeInfo.isSystem()) {
|
||||
if (path.getFileExtension() == null) {
|
||||
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
||||
} else {
|
||||
includeKind = IncludeKind.SYSTEM_WITH_EXTENSION;
|
||||
}
|
||||
} else if (isPartnerFile(path)) {
|
||||
includeKind = IncludeKind.PARTNER;
|
||||
} else {
|
||||
includeKind = IncludeKind.EXTERNAL;
|
||||
}
|
||||
return fPreferences.includeStyles.get(includeKind);
|
||||
}
|
||||
|
||||
private static boolean fileExists(String absolutePath) {
|
||||
return new File(absolutePath).exists();
|
||||
}
|
||||
|
||||
public Set<IPath> getHeadersToInclude() {
|
||||
return fHeadersToInclude;
|
||||
/**
|
||||
* Checks if the given path points to a partner header of the current translation unit.
|
||||
* A header is considered a partner if its name without extension is the same as the name of
|
||||
* the translation unit, or the name of the translation unit differs by one of the suffixes
|
||||
* used for test files.
|
||||
*/
|
||||
public boolean isPartnerFile(IPath path) {
|
||||
String headerName = path.removeFileExtension().lastSegment();
|
||||
String sourceName = getTranslationUnit().getLocation().removeFileExtension().lastSegment();
|
||||
if (headerName.equals(sourceName))
|
||||
return true;
|
||||
if (sourceName.startsWith(headerName)) {
|
||||
int pos = headerName.length();
|
||||
while (pos < sourceName.length() && !Character.isLetterOrDigit(sourceName.charAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
if (pos == sourceName.length())
|
||||
return true;
|
||||
String suffix = sourceName.substring(pos);
|
||||
for (String s : fPreferences.partnerFileSuffixes) {
|
||||
if (suffix.equalsIgnoreCase(s))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final void addHeaderToInclude(IPath header) {
|
||||
fHeadersToInclude.add(header);
|
||||
}
|
||||
|
||||
public final boolean isToBeIncluded(IPath header) {
|
||||
return fHeadersToInclude.contains(header);
|
||||
}
|
||||
|
||||
public Set<IPath> getHeadersAlreadyIncluded() {
|
||||
return fHeadersAlreadyIncluded;
|
||||
}
|
||||
|
||||
public final void addHeaderAlreadyIncluded(IPath header) {
|
||||
fHeadersAlreadyIncluded.add(header);
|
||||
}
|
||||
|
||||
public final boolean isAlreadyIncluded(IPath header) {
|
||||
return fHeadersAlreadyIncluded.contains(header);
|
||||
}
|
||||
|
||||
public final boolean isIncluded(IPath header) {
|
||||
return fHeadersAlreadyIncluded.contains(header) || fHeadersToInclude.contains(header);
|
||||
}
|
||||
|
||||
public final void addHeaderIncludedPreviously(IPath header) {
|
||||
fHeadersIncludedPreviously.add(header);
|
||||
}
|
||||
|
||||
public final boolean wasIncludedPreviously(IPath header) {
|
||||
return fHeadersIncludedPreviously.contains(header);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2013 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.internal.corext.codemanipulation;
|
||||
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
|
||||
|
||||
/**
|
||||
* Represents a new or an existing include statement together with the style associated with it.
|
||||
*/
|
||||
public class StyledInclude implements Comparable<StyledInclude> {
|
||||
private final IPath header; // null for existing unresolved includes
|
||||
private final IncludeInfo includeInfo; // never null
|
||||
private final IncludeGroupStyle style;
|
||||
private IASTPreprocessorIncludeStatement existingInclude;
|
||||
|
||||
/** Initializes a StyledInclude object for a new include */
|
||||
public StyledInclude(IPath header, IncludeInfo includeInfo, IncludeGroupStyle style) {
|
||||
this(header, includeInfo, style, null);
|
||||
if (header == null)
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an include prototype object for an existing include. {@code header} may be
|
||||
* {@code null} if the include was not resolved.
|
||||
*/
|
||||
public StyledInclude(IPath header, IncludeInfo includeInfo, IncludeGroupStyle style,
|
||||
IASTPreprocessorIncludeStatement existingInclude) {
|
||||
if (includeInfo == null)
|
||||
throw new NullPointerException();
|
||||
this.header = header;
|
||||
this.includeInfo = includeInfo;
|
||||
this.style = style;
|
||||
this.existingInclude = existingInclude;
|
||||
}
|
||||
|
||||
public IPath getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public IncludeInfo getIncludeInfo() {
|
||||
return includeInfo;
|
||||
}
|
||||
|
||||
public IncludeGroupStyle getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public IASTPreprocessorIncludeStatement getExistingInclude() {
|
||||
return existingInclude;
|
||||
}
|
||||
|
||||
public void setExistingInclude(IASTPreprocessorIncludeStatement existingInclude) {
|
||||
this.existingInclude = existingInclude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(StyledInclude other) {
|
||||
return includeInfo.compareTo(other.includeInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (header != null)
|
||||
return header.hashCode(); // includeInfo is ignored if header is not null
|
||||
return includeInfo.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
StyledInclude other = (StyledInclude) obj;
|
||||
if (header != null)
|
||||
return header.equals(other.header); // includeInfo is ignored if header is not null
|
||||
if (other.header != null)
|
||||
return false;
|
||||
return includeInfo.equals(other.includeInfo);
|
||||
}
|
||||
|
||||
/** For debugging only */
|
||||
@Override
|
||||
public String toString() {
|
||||
return header != null ? header.toPortableString() : includeInfo.toString();
|
||||
}
|
||||
}
|
|
@ -87,12 +87,12 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.AddIncludesOperation;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.InclusionContext;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.CHelpProviderManager;
|
||||
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
|
||||
import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeInfo;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.InclusionContext;
|
||||
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
||||
|
||||
/**
|
||||
|
@ -205,7 +205,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction {
|
|||
*/
|
||||
private void deduceInclude(ITextSelection selection, IIndex index, IASTTranslationUnit ast, String[] lookupName)
|
||||
throws CoreException {
|
||||
fContext = new InclusionContext(fTu, index);
|
||||
fContext = new InclusionContext(fTu);
|
||||
IASTNodeSelector selector = ast.getNodeSelector(fTu.getLocation().toOSString());
|
||||
IASTName name = selector.findEnclosingName(selection.getOffset(), selection.getLength());
|
||||
if (name == null) {
|
||||
|
|
|
@ -30,10 +30,12 @@ import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
|
|||
* Dialog-based header chooser.
|
||||
*/
|
||||
public class InteractiveHeaderChooser implements IHeaderChooser {
|
||||
private final String title;
|
||||
private final Shell shell;
|
||||
Map<Collection<IPath>, IPath> userChoiceCache;
|
||||
private final Map<Collection<IPath>, IPath> userChoiceCache;
|
||||
|
||||
public InteractiveHeaderChooser(Shell shell) {
|
||||
public InteractiveHeaderChooser(String title, Shell shell) {
|
||||
this.title = title;
|
||||
this.shell = shell;
|
||||
userChoiceCache = new HashMap<Collection<IPath>, IPath>();
|
||||
}
|
||||
|
@ -62,7 +64,7 @@ public class InteractiveHeaderChooser implements IHeaderChooser {
|
|||
ElementListSelectionDialog dialog =
|
||||
new ElementListSelectionDialog(shell, new LabelProvider());
|
||||
dialog.setElements(elemArray);
|
||||
dialog.setTitle(CEditorMessages.OrganizeIncludes_label);
|
||||
dialog.setTitle(title);
|
||||
dialog.setMessage(NLS.bind(CEditorMessages.OrganizeIncludes_choose_header, bindingName));
|
||||
if (dialog.open() == Window.OK) {
|
||||
selectedElement[0] = (IPath) dialog.getFirstResult();
|
||||
|
|
|
@ -49,7 +49,7 @@ import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
|
|||
public class OrganizeIncludesAction extends TextEditorAction {
|
||||
/**
|
||||
* Constructor
|
||||
* @param editor The editor on which this organize includes action should operate.
|
||||
* @param editor The editor on which this Organize Includes action should operate.
|
||||
*/
|
||||
public OrganizeIncludesAction(ITextEditor editor) {
|
||||
super(CEditorMessages.getBundleForConstructedKeys(), "OrganizeIncludes.", editor); //$NON-NLS-1$
|
||||
|
@ -67,7 +67,8 @@ public class OrganizeIncludesAction extends TextEditorAction {
|
|||
return;
|
||||
}
|
||||
|
||||
final IHeaderChooser headerChooser = new InteractiveHeaderChooser(editor.getSite().getShell());
|
||||
final IHeaderChooser headerChooser = new InteractiveHeaderChooser(
|
||||
CEditorMessages.OrganizeIncludes_label, editor.getSite().getShell());
|
||||
final String lineDelimiter = getLineDelimiter(editor);
|
||||
final List<TextEdit> edits = new ArrayList<TextEdit>();
|
||||
SharedASTJob job = new SharedASTJob(CEditorMessages.OrganizeIncludes_action, tu) {
|
||||
|
|
|
@ -56,11 +56,12 @@ import org.eclipse.ui.XMLMemento;
|
|||
|
||||
import com.ibm.icu.text.Collator;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.ResizableStatusDialog;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.HeaderSubstitutionMap;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeInfo;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeMap;
|
||||
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ComboDialogField;
|
||||
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
|
||||
|
|
|
@ -111,7 +111,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
|||
* must be defined and a set of bindings that must be declared.
|
||||
*/
|
||||
public class BindingClassifier {
|
||||
private final InclusionContext fContext;
|
||||
private final IncludeCreationContext fContext;
|
||||
private final IncludePreferences fPreferences;
|
||||
/** The bindings which require a full definition. */
|
||||
private final Set<IBinding> fBindingsToDefine;
|
||||
|
@ -126,7 +126,7 @@ public class BindingClassifier {
|
|||
/**
|
||||
* @param context the context for binding classification
|
||||
*/
|
||||
public BindingClassifier(InclusionContext context) {
|
||||
public BindingClassifier(IncludeCreationContext context) {
|
||||
fContext = context;
|
||||
fPreferences = context.getPreferences();
|
||||
fBindingsToDefine = new HashSet<IBinding>();
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.eclipse.ui.XMLMemento;
|
|||
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
|
||||
/**
|
||||
* A set of header file substitution rules.
|
||||
*/
|
||||
|
|
|
@ -32,13 +32,14 @@ import org.eclipse.cdt.ui.CUIPlugin;
|
|||
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||
|
||||
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
|
||||
public class HeaderSubstitutor {
|
||||
private final InclusionContext fContext;
|
||||
private final IncludeCreationContext fContext;
|
||||
private IncludeMap[] fIncludeMaps;
|
||||
private SymbolExportMap fSymbolExportMap;
|
||||
|
||||
public HeaderSubstitutor(InclusionContext context) {
|
||||
public HeaderSubstitutor(IncludeCreationContext context) {
|
||||
fContext = context;
|
||||
fIncludeMaps = new IncludeMap[] { new IncludeMap(true), new IncludeMap(false) };
|
||||
IPreferencesService preferences = Platform.getPreferencesService();
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2013 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.internal.ui.refactoring.includes;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexInclude;
|
||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.InclusionContext;
|
||||
|
||||
/**
|
||||
* Context for managing include statements.
|
||||
*/
|
||||
public class IncludeCreationContext extends InclusionContext {
|
||||
private final IIndex fIndex;
|
||||
private final Set<IPath> fHeadersToInclude;
|
||||
private final Set<IPath> fHeadersAlreadyIncluded;
|
||||
private final Set<IPath> fHeadersIncludedPreviously;
|
||||
|
||||
public IncludeCreationContext(ITranslationUnit tu, IIndex index) {
|
||||
super(tu);
|
||||
fIndex = index;
|
||||
fHeadersToInclude = new HashSet<IPath>();
|
||||
fHeadersAlreadyIncluded = new HashSet<IPath>();
|
||||
fHeadersIncludedPreviously = new HashSet<IPath>();
|
||||
}
|
||||
|
||||
public char[] getSourceContents() {
|
||||
return getTranslationUnit().getContents();
|
||||
}
|
||||
|
||||
public IIndex getIndex() {
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
public boolean isCXXLanguage() {
|
||||
return getTranslationUnit().isCXXLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes headers that are exported by other headers that will be included
|
||||
*/
|
||||
public void removeExportedHeaders() throws CoreException {
|
||||
// Index files keyed by their absolute paths.
|
||||
Map<IPath, IIndexFile> filesByPath = new HashMap<IPath, IIndexFile>();
|
||||
for (IIndexFile file : fIndex.getAllFiles()) {
|
||||
IPath path = getPath(file);
|
||||
filesByPath.put(path, file);
|
||||
}
|
||||
|
||||
Set<IPath> exportedHeaders = new HashSet<IPath>();
|
||||
for (IPath path : fHeadersToInclude) {
|
||||
if (!exportedHeaders.contains(path)) {
|
||||
IIndexFile file = filesByPath.get(path);
|
||||
if (file != null) { // file can be null if the header was not indexed.
|
||||
ArrayDeque<IIndexFile> queue = new ArrayDeque<IIndexFile>();
|
||||
queue.add(file);
|
||||
while ((file = queue.pollFirst()) != null) {
|
||||
for (IIndexInclude include : file.getIncludes()) {
|
||||
if (getPreferences().allowIndirectInclusion || include.isIncludedFileExported()) {
|
||||
file = fIndex.resolveInclude(include);
|
||||
if (file != null) {
|
||||
if (exportedHeaders.add(getPath(file)))
|
||||
queue.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fHeadersToInclude.removeAll(exportedHeaders);
|
||||
}
|
||||
|
||||
private static IPath getPath(IIndexFile file) throws CoreException {
|
||||
return IndexLocationFactory.getAbsolutePath(file.getLocation());
|
||||
}
|
||||
|
||||
public Set<IPath> getHeadersToInclude() {
|
||||
return fHeadersToInclude;
|
||||
}
|
||||
|
||||
public final void addHeaderToInclude(IPath header) {
|
||||
fHeadersToInclude.add(header);
|
||||
}
|
||||
|
||||
public final boolean isToBeIncluded(IPath header) {
|
||||
return fHeadersToInclude.contains(header);
|
||||
}
|
||||
|
||||
public Set<IPath> getHeadersAlreadyIncluded() {
|
||||
return fHeadersAlreadyIncluded;
|
||||
}
|
||||
|
||||
public final void addHeaderAlreadyIncluded(IPath header) {
|
||||
fHeadersAlreadyIncluded.add(header);
|
||||
}
|
||||
|
||||
public final boolean isAlreadyIncluded(IPath header) {
|
||||
return fHeadersAlreadyIncluded.contains(header);
|
||||
}
|
||||
|
||||
public final boolean isIncluded(IPath header) {
|
||||
return fHeadersAlreadyIncluded.contains(header) || fHeadersToInclude.contains(header);
|
||||
}
|
||||
|
||||
public void addHeadersIncludedPreviously(IASTPreprocessorIncludeStatement[] includes) {
|
||||
for (IASTPreprocessorIncludeStatement include : includes) {
|
||||
if (include.isPartOfTranslationUnitFile()) {
|
||||
String path = include.getPath();
|
||||
// An empty path means that the include was not resolved.
|
||||
if (!path.isEmpty())
|
||||
fHeadersIncludedPreviously.add(Path.fromOSString(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean wasIncludedPreviously(IPath header) {
|
||||
return fHeadersIncludedPreviously.contains(header);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import java.io.StringReader;
|
|||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.ui.IMemento;
|
||||
|
@ -262,4 +263,21 @@ public class IncludeGroupStyle implements Comparable<IncludeGroupStyle> {
|
|||
return c;
|
||||
return includeKind.ordinal() - other.includeKind.ordinal();
|
||||
}
|
||||
|
||||
|
||||
public IncludeGroupStyle getGroupingStyle(Map<IncludeKind, IncludeGroupStyle> stylesMap) {
|
||||
if (keepTogether)
|
||||
return this;
|
||||
IncludeGroupStyle parent = getParentStyle(stylesMap);
|
||||
if (parent != null && (parent.keepTogether || parent.includeKind == IncludeKind.OTHER))
|
||||
return parent;
|
||||
return stylesMap.get(IncludeKind.OTHER);
|
||||
}
|
||||
|
||||
public IncludeGroupStyle getParentStyle(Map<IncludeKind, IncludeGroupStyle> stylesMap) {
|
||||
IncludeKind kind = includeKind.parent;
|
||||
if (kind == null)
|
||||
return null;
|
||||
return stylesMap.get(kind);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import java.util.Set;
|
|||
|
||||
import org.eclipse.ui.IMemento;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
|
||||
/**
|
||||
* A set of header file substitution rules.
|
||||
*/
|
||||
|
|
|
@ -16,6 +16,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getEnd
|
|||
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeEndOffset;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeOffset;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getStartingLineNumber;
|
||||
import static org.eclipse.cdt.internal.ui.refactoring.includes.IncludeUtil.isContainedInRegion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -26,8 +27,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
@ -89,9 +88,8 @@ import org.eclipse.cdt.internal.core.parser.scanner.CharArray;
|
|||
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeGuardDetection;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.StyledInclude;
|
||||
|
||||
/**
|
||||
* Organizes the include directives and forward declarations of a source or header file.
|
||||
|
@ -99,88 +97,44 @@ import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.Includ
|
|||
public class IncludeOrganizer {
|
||||
private static boolean DEBUG_HEADER_SUBSTITUTION = "true".equalsIgnoreCase(Platform.getDebugOption(CUIPlugin.PLUGIN_ID + "/debug/includeOrganizer/headerSubstitution")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
private static class IncludePrototype implements Comparable<IncludePrototype> {
|
||||
final IPath header; // null for existing unresolved includes
|
||||
final IncludeInfo includeInfo; // never null
|
||||
IASTPreprocessorIncludeStatement existingInclude; // null for newly added includes
|
||||
final boolean required; // true if the header has to be included
|
||||
final IncludeGroupStyle style;
|
||||
private static final Collator COLLATOR = Collator.getInstance();
|
||||
|
||||
/** Initializes an include prototype for a new include */
|
||||
/**
|
||||
* Represents a new or an existing include statement.
|
||||
*/
|
||||
private static class IncludePrototype extends StyledInclude {
|
||||
private final boolean required; // true if the header has to be included
|
||||
|
||||
/** Initializes an include prototype object for a new include */
|
||||
IncludePrototype(IPath header, IncludeInfo includeInfo, IncludeGroupStyle style) {
|
||||
if (includeInfo == null)
|
||||
throw new NullPointerException();
|
||||
this.header = header;
|
||||
this.includeInfo = includeInfo;
|
||||
this.style = style;
|
||||
super(header, includeInfo, style);
|
||||
this.required = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an include prototype for an existing include. {@code header} may be
|
||||
* Initializes an include prototype object for an existing include. {@code header} may be
|
||||
* {@code null} if the include was not resolved.
|
||||
*/
|
||||
IncludePrototype(IASTPreprocessorIncludeStatement include, IPath header,
|
||||
IncludeInfo includeInfo, IncludeGroupStyle style) {
|
||||
if (includeInfo == null)
|
||||
throw new NullPointerException();
|
||||
this.existingInclude = include;
|
||||
this.header = header;
|
||||
this.includeInfo = includeInfo;
|
||||
this.style = style;
|
||||
IncludePrototype(IPath header, IncludeInfo includeInfo, IncludeGroupStyle style,
|
||||
IASTPreprocessorIncludeStatement existingInclude) {
|
||||
super(header, includeInfo, style, existingInclude);
|
||||
this.required = false;
|
||||
}
|
||||
|
||||
public void updateFrom(IncludePrototype other) {
|
||||
this.existingInclude = other.existingInclude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (header != null)
|
||||
return header.hashCode(); // includeInfo is ignored if header is not null
|
||||
return includeInfo.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
IncludePrototype other = (IncludePrototype) obj;
|
||||
if (header != null)
|
||||
return header.equals(other.header); // includeInfo is ignored if header is not null
|
||||
if (other.header != null)
|
||||
return false;
|
||||
return includeInfo.equals(other.includeInfo);
|
||||
}
|
||||
|
||||
/** For debugging only */
|
||||
@Override
|
||||
public String toString() {
|
||||
return header != null ? header.toPortableString() : includeInfo.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(IncludePrototype other) {
|
||||
return includeInfo.compareTo(other.includeInfo);
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Collator COLLATOR = Collator.getInstance();
|
||||
|
||||
private final IHeaderChooser fHeaderChooser;
|
||||
private final InclusionContext fContext;
|
||||
private final IncludeCreationContext fContext;
|
||||
private final String fLineDelimiter;
|
||||
|
||||
public IncludeOrganizer(ITranslationUnit tu, IIndex index, String lineDelimiter,
|
||||
IHeaderChooser headerChooser) {
|
||||
fLineDelimiter = lineDelimiter;
|
||||
fHeaderChooser = headerChooser;
|
||||
fContext = new InclusionContext(tu, index);
|
||||
fContext = new IncludeCreationContext(tu, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,14 +149,7 @@ public class IncludeOrganizer {
|
|||
Set<IBinding> bindingsToDefine = bindingClassifier.getBindingsToDefine();
|
||||
|
||||
IASTPreprocessorIncludeStatement[] existingIncludes = ast.getIncludeDirectives();
|
||||
for (IASTPreprocessorIncludeStatement include : existingIncludes) {
|
||||
if (include.isPartOfTranslationUnitFile()) {
|
||||
String path = include.getPath();
|
||||
// An empty path means that the include was not resolved.
|
||||
if (!path.isEmpty())
|
||||
fContext.addHeaderIncludedPreviously(Path.fromOSString(path));
|
||||
}
|
||||
}
|
||||
fContext.addHeadersIncludedPreviously(existingIncludes);
|
||||
|
||||
HeaderSubstitutor headerSubstitutor = new HeaderSubstitutor(fContext);
|
||||
// Create the list of header files which have to be included by examining the list of
|
||||
|
@ -218,12 +165,12 @@ public class IncludeOrganizer {
|
|||
new HashMap<IncludePrototype, IncludePrototype>();
|
||||
// Put the new includes into includePrototypes.
|
||||
for (IPath header : fContext.getHeadersToInclude()) {
|
||||
IncludeGroupStyle style = getIncludeStyle(header);
|
||||
IncludeGroupStyle style = fContext.getIncludeStyle(header);
|
||||
IncludeInfo includeInfo = createIncludeInfo(header, style);
|
||||
IncludePrototype prototype = new IncludePrototype(header, includeInfo, style);
|
||||
updateIncludePrototypes(includePrototypes, prototype);
|
||||
}
|
||||
// Put the existing includes into includePrototypes.
|
||||
// Add existing includes to includePrototypes.
|
||||
for (IASTPreprocessorIncludeStatement include : existingIncludes) {
|
||||
if (include.isPartOfTranslationUnitFile()) {
|
||||
String name = new String(include.getName().getSimpleID());
|
||||
|
@ -232,14 +179,15 @@ public class IncludeOrganizer {
|
|||
// An empty path means that the include was not resolved.
|
||||
IPath header = path.isEmpty() ? null : Path.fromOSString(path);
|
||||
IncludeGroupStyle style =
|
||||
header != null ? getIncludeStyle(header) : getIncludeStyle(includeInfo);
|
||||
IncludePrototype prototype = new IncludePrototype(include, header, includeInfo, style);
|
||||
header != null ? fContext.getIncludeStyle(header) : fContext.getIncludeStyle(includeInfo);
|
||||
IncludePrototype prototype = new IncludePrototype(header, includeInfo, style, include);
|
||||
updateIncludePrototypes(includePrototypes, prototype);
|
||||
}
|
||||
}
|
||||
|
||||
NodeCommentMap commentedNodeMap = ASTCommenter.getCommentedNodeMap(ast);
|
||||
IRegion includeReplacementRegion = getSafeIncludeReplacementRegion(ast, commentedNodeMap);
|
||||
IRegion includeReplacementRegion =
|
||||
getSafeIncludeReplacementRegion(fContext.getSourceContents(), ast, commentedNodeMap);
|
||||
|
||||
IncludePreferences preferences = fContext.getPreferences();
|
||||
boolean allowReordering = preferences.allowReordering || existingIncludes.length == 0;
|
||||
|
@ -250,9 +198,9 @@ public class IncludeOrganizer {
|
|||
List<IncludePrototype>[] groupedPrototypes =
|
||||
(List<IncludePrototype>[]) new List<?>[preferences.includeStyles.size()];
|
||||
for (IncludePrototype prototype : includePrototypes.keySet()) {
|
||||
if (prototype.existingInclude == null
|
||||
|| (allowReordering && isContainedInRegion(prototype.existingInclude, includeReplacementRegion))) {
|
||||
IncludeGroupStyle groupingStyle = getGroupingStyle(prototype.style);
|
||||
if (prototype.getExistingInclude() == null
|
||||
|| (allowReordering && isContainedInRegion(prototype.getExistingInclude(), includeReplacementRegion))) {
|
||||
IncludeGroupStyle groupingStyle = prototype.getStyle().getGroupingStyle(preferences.includeStyles);
|
||||
// If reordering is not allowed, group everything together.
|
||||
int position = allowReordering ? groupingStyle.getOrder() : 0;
|
||||
List<IncludePrototype> prototypes = groupedPrototypes[position];
|
||||
|
@ -262,15 +210,15 @@ public class IncludeOrganizer {
|
|||
}
|
||||
prototypes.add(prototype);
|
||||
}
|
||||
if (!allowReordering && prototype.existingInclude != null
|
||||
&& !prototype.required && prototype.header != null // Unused and resolved.
|
||||
&& isContainedInRegion(prototype.existingInclude, includeReplacementRegion)) {
|
||||
if (!allowReordering && prototype.getExistingInclude() != null
|
||||
&& !prototype.isRequired() && prototype.getHeader() != null // Unused and resolved.
|
||||
&& isContainedInRegion(prototype.getExistingInclude(), includeReplacementRegion)) {
|
||||
switch (preferences.unusedStatementsDisposition) {
|
||||
case REMOVE:
|
||||
createDelete(prototype.existingInclude, edits);
|
||||
createDelete(prototype.getExistingInclude(), edits);
|
||||
break;
|
||||
case COMMENT_OUT:
|
||||
createCommentOut(prototype.existingInclude, edits);
|
||||
createCommentOut(prototype.getExistingInclude(), edits);
|
||||
break;
|
||||
case KEEP:
|
||||
break;
|
||||
|
@ -283,9 +231,9 @@ public class IncludeOrganizer {
|
|||
for (List<IncludePrototype> prototypes : groupedPrototypes) {
|
||||
if (prototypes != null && !prototypes.isEmpty()) {
|
||||
Collections.sort(prototypes);
|
||||
IncludeGroupStyle style = prototypes.get(0).style;
|
||||
IncludeGroupStyle groupingStyle = getGroupingStyle(style);
|
||||
IncludeGroupStyle parentStyle = getParentStyle(groupingStyle);
|
||||
IncludeGroupStyle style = prototypes.get(0).getStyle();
|
||||
IncludeGroupStyle groupingStyle = style.getGroupingStyle(preferences.includeStyles);
|
||||
IncludeGroupStyle parentStyle = groupingStyle.getParentStyle(preferences.includeStyles);
|
||||
boolean blankLineBefore = groupingStyle.isBlankLineBefore() ||
|
||||
(parentStyle != null && parentStyle != previousParentStyle &&
|
||||
parentStyle.isKeepTogether() && parentStyle.isBlankLineBefore());
|
||||
|
@ -294,9 +242,9 @@ public class IncludeOrganizer {
|
|||
includeDirectives.add(""); // Blank line separator //$NON-NLS-1$
|
||||
for (IncludePrototype prototype : prototypes) {
|
||||
String trailingComment = ""; //$NON-NLS-1$
|
||||
IASTPreprocessorIncludeStatement include = prototype.existingInclude;
|
||||
IASTPreprocessorIncludeStatement include = prototype.getExistingInclude();
|
||||
if (include == null
|
||||
|| (allowReordering && isContainedInRegion(include, includeReplacementRegion))) {
|
||||
|| (allowReordering && IncludeUtil.isContainedInRegion(include, includeReplacementRegion))) {
|
||||
if (include != null) {
|
||||
List<IASTComment> comments = commentedNodeMap.getTrailingCommentsForNode(include);
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
@ -522,7 +470,7 @@ public class IncludeOrganizer {
|
|||
IASTFileLocation location = include.getFileLocation();
|
||||
int offset = location.getNodeOffset();
|
||||
if (fContext.getTranslationUnit().isCXXLanguage()) {
|
||||
offset = getLineStart(offset);
|
||||
offset = getLineStart(fContext.getSourceContents(), offset);
|
||||
edits.add(new InsertEdit(offset, "//")); //$NON-NLS-1$
|
||||
} else {
|
||||
edits.add(new InsertEdit(offset, "/*")); //$NON-NLS-1$
|
||||
|
@ -535,8 +483,8 @@ public class IncludeOrganizer {
|
|||
IASTFileLocation location = include.getFileLocation();
|
||||
int offset = location.getNodeOffset();
|
||||
int endOffset = offset + location.getNodeLength();
|
||||
offset = getLineStart(offset);
|
||||
endOffset = skipToNextLine(endOffset);
|
||||
offset = getLineStart(fContext.getSourceContents(), offset);
|
||||
endOffset = skipToNextLine(fContext.getSourceContents(), endOffset);
|
||||
edits.add(new DeleteEdit(offset, endOffset - offset));
|
||||
}
|
||||
|
||||
|
@ -546,16 +494,12 @@ public class IncludeOrganizer {
|
|||
if (existing == null) {
|
||||
includePrototypes.put(prototype, prototype);
|
||||
} else {
|
||||
existing.updateFrom(prototype);
|
||||
existing.setExistingInclude(prototype.getExistingInclude());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isContainedInRegion(IASTNode node, IRegion region) {
|
||||
return getNodeOffset(node) >= region.getOffset()
|
||||
&& getNodeEndOffset(node) <= region.getOffset() + region.getLength();
|
||||
}
|
||||
|
||||
private IRegion getSafeIncludeReplacementRegion(IASTTranslationUnit ast, NodeCommentMap commentMap) {
|
||||
static IRegion getSafeIncludeReplacementRegion(char[] contents, IASTTranslationUnit ast,
|
||||
NodeCommentMap commentMap) {
|
||||
int maxSafeOffset = ast.getFileLocation().getNodeLength();
|
||||
IASTDeclaration[] declarations = ast.getDeclarations(true);
|
||||
if (declarations.length != 0)
|
||||
|
@ -592,22 +536,22 @@ public class IncludeOrganizer {
|
|||
}
|
||||
if (includeOffset < 0) {
|
||||
if (includeGuardEndOffset >= 0) {
|
||||
includeOffset = skipToNextLine(includeGuardEndOffset);
|
||||
includeOffset = skipToNextLine(contents, includeGuardEndOffset);
|
||||
} else {
|
||||
includeOffset = 0;
|
||||
}
|
||||
if (!topCommentSkipped) {
|
||||
// Skip the first comment block near the top of the file.
|
||||
includeOffset = skipStandaloneCommentBlock(includeOffset, maxSafeOffset, ast.getComments(), commentMap);
|
||||
includeOffset = skipStandaloneCommentBlock(contents, includeOffset, maxSafeOffset, ast.getComments(), commentMap);
|
||||
}
|
||||
includeEndOffset = includeOffset;
|
||||
} else {
|
||||
includeEndOffset = skipToNextLine(includeEndOffset);
|
||||
includeEndOffset = skipToNextLine(contents, includeEndOffset);
|
||||
}
|
||||
return new Region(includeOffset, includeEndOffset - includeOffset);
|
||||
}
|
||||
|
||||
private int getNumberOfIncludeGuardStatementsToSkip(IASTTranslationUnit ast) {
|
||||
private static int getNumberOfIncludeGuardStatementsToSkip(IASTTranslationUnit ast) {
|
||||
IASTPreprocessorStatement statement = findFirstPreprocessorStatement(ast);
|
||||
if (statement == null)
|
||||
return 0;
|
||||
|
@ -620,7 +564,7 @@ public class IncludeOrganizer {
|
|||
}
|
||||
char[] contents = ast.getRawSignature().toCharArray();
|
||||
if (offset != 0)
|
||||
Arrays.copyOfRange(contents, offset, contents.length);
|
||||
contents = Arrays.copyOfRange(contents, offset, contents.length);
|
||||
CharArrayIntMap ppKeywords= new CharArrayIntMap(40, -1);
|
||||
Keywords.addKeywordsPreprocessor(ppKeywords);
|
||||
if (IncludeGuardDetection.detectIncludeGuard(new CharArray(contents), new LexerOptions(), ppKeywords) != null) {
|
||||
|
@ -629,39 +573,38 @@ public class IncludeOrganizer {
|
|||
return num;
|
||||
}
|
||||
|
||||
private IASTPreprocessorStatement findFirstPreprocessorStatement(IASTTranslationUnit ast) {
|
||||
private static IASTPreprocessorStatement findFirstPreprocessorStatement(IASTTranslationUnit ast) {
|
||||
for (IASTPreprocessorStatement statement : ast.getAllPreprocessorStatements()) {
|
||||
if (statement.isPartOfTranslationUnitFile())
|
||||
return statement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private boolean isPragmaOnce(IASTPreprocessorStatement statement) {
|
||||
|
||||
private static boolean isPragmaOnce(IASTPreprocessorStatement statement) {
|
||||
if (!(statement instanceof IASTPreprocessorPragmaStatement))
|
||||
return false;
|
||||
return CharArrayUtils.equals(((IASTPreprocessorPragmaStatement) statement).getMessage(), "once"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private int skipToNextLine(int offset) {
|
||||
char[] contents = fContext.getTranslationUnit().getContents();
|
||||
while (offset < contents.length) {
|
||||
if (contents[offset++] == '\n')
|
||||
private static int skipToNextLine(char[] text, int offset) {
|
||||
while (offset < text.length) {
|
||||
if (text[offset++] == '\n')
|
||||
break;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
private int getLineStart(int offset) {
|
||||
char[] contents = fContext.getTranslationUnit().getContents();
|
||||
private static int getLineStart(char[] text, int offset) {
|
||||
while (--offset >= 0) {
|
||||
if (contents[offset] == '\n')
|
||||
if (text[offset] == '\n')
|
||||
break;
|
||||
}
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
private int skipToNextLineAfterNode(IASTNode node) {
|
||||
return skipToNextLine(getNodeEndOffset(node));
|
||||
private static int skipToNextLineAfterNode(char[] text, IASTNode node) {
|
||||
return skipToNextLine(text, getNodeEndOffset(node));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -720,7 +663,8 @@ public class IncludeOrganizer {
|
|||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private int skipStandaloneCommentBlock(int offset, int endOffset, IASTComment[] comments, NodeCommentMap commentMap) {
|
||||
private static int skipStandaloneCommentBlock(char[] contents, int offset, int endOffset,
|
||||
IASTComment[] comments, NodeCommentMap commentMap) {
|
||||
Map<IASTComment, IASTNode> inverseLeadingMap = new HashMap<IASTComment, IASTNode>();
|
||||
for (Map.Entry<IASTNode, List<IASTComment>> entry : commentMap.getLeadingMap().entrySet()) {
|
||||
IASTNode node = entry.getKey();
|
||||
|
@ -753,11 +697,11 @@ public class IncludeOrganizer {
|
|||
for (int j = 1; j < leadingComments.size(); j++) {
|
||||
comment = leadingComments.get(j);
|
||||
if (getStartingLineNumber(comment) > getEndingLineNumber(previous) + 1)
|
||||
return skipToNextLineAfterNode(previous);
|
||||
return skipToNextLineAfterNode(contents, previous);
|
||||
previous = comment;
|
||||
}
|
||||
if (getStartingLineNumber(node) > getEndingLineNumber(previous) + 1)
|
||||
return skipToNextLineAfterNode(previous);
|
||||
return skipToNextLineAfterNode(contents, previous);
|
||||
}
|
||||
node = inverseFreestandingMap.get(comment);
|
||||
if (node != null) {
|
||||
|
@ -766,7 +710,7 @@ public class IncludeOrganizer {
|
|||
for (int j = 1; j < freestandingComments.size(); j++) {
|
||||
comment = freestandingComments.get(j);
|
||||
if (getStartingLineNumber(comment) > getEndingLineNumber(previous) + 1)
|
||||
return skipToNextLineAfterNode(previous);
|
||||
return skipToNextLineAfterNode(contents, previous);
|
||||
previous = comment;
|
||||
}
|
||||
}
|
||||
|
@ -775,77 +719,6 @@ public class IncludeOrganizer {
|
|||
return offset;
|
||||
}
|
||||
|
||||
private IncludeGroupStyle getGroupingStyle(IncludeGroupStyle style) {
|
||||
if (style.isKeepTogether())
|
||||
return style;
|
||||
IncludeGroupStyle parent = getParentStyle(style);
|
||||
if (parent != null && (parent.isKeepTogether() || parent.getIncludeKind() == IncludeKind.OTHER))
|
||||
return parent;
|
||||
return fContext.getPreferences().includeStyles.get(IncludeKind.OTHER);
|
||||
}
|
||||
|
||||
private IncludeGroupStyle getParentStyle(IncludeGroupStyle style) {
|
||||
IncludeKind kind = style.getIncludeKind().parent;
|
||||
if (kind == null)
|
||||
return null;
|
||||
return fContext.getPreferences().includeStyles.get(kind);
|
||||
}
|
||||
|
||||
private IncludeGroupStyle getIncludeStyle(IPath headerPath) {
|
||||
IncludeKind includeKind;
|
||||
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(headerPath);
|
||||
if (includeInfo != null && includeInfo.isSystem()) {
|
||||
if (headerPath.getFileExtension() == null) {
|
||||
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
||||
} else {
|
||||
includeKind = IncludeKind.SYSTEM_WITH_EXTENSION;
|
||||
}
|
||||
} else if (isPartnerFile(headerPath)) {
|
||||
includeKind = IncludeKind.PARTNER;
|
||||
} else {
|
||||
IPath dir = fContext.getCurrentDirectory();
|
||||
if (dir.isPrefixOf(headerPath)) {
|
||||
if (headerPath.segmentCount() == dir.segmentCount() + 1) {
|
||||
includeKind = IncludeKind.IN_SAME_FOLDER;
|
||||
} else {
|
||||
includeKind = IncludeKind.IN_SUBFOLDER;
|
||||
}
|
||||
} else {
|
||||
IFile[] files = ResourceLookup.findFilesForLocation(headerPath);
|
||||
if (files.length == 0) {
|
||||
includeKind = IncludeKind.EXTERNAL;
|
||||
} else {
|
||||
IProject project = fContext.getProject();
|
||||
includeKind = IncludeKind.IN_OTHER_PROJECT;
|
||||
for (IFile file : files) {
|
||||
if (file.getProject().equals(project)) {
|
||||
includeKind = IncludeKind.IN_SAME_PROJECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fContext.getPreferences().includeStyles.get(includeKind);
|
||||
}
|
||||
|
||||
private IncludeGroupStyle getIncludeStyle(IncludeInfo includeInfo) {
|
||||
IncludeKind includeKind;
|
||||
IPath path = Path.fromPortableString(includeInfo.getName());
|
||||
if (includeInfo.isSystem()) {
|
||||
if (path.getFileExtension() == null) {
|
||||
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
||||
} else {
|
||||
includeKind = IncludeKind.SYSTEM_WITH_EXTENSION;
|
||||
}
|
||||
} else if (isPartnerFile(path)) {
|
||||
includeKind = IncludeKind.PARTNER;
|
||||
} else {
|
||||
includeKind = IncludeKind.EXTERNAL;
|
||||
}
|
||||
return fContext.getPreferences().includeStyles.get(includeKind);
|
||||
}
|
||||
|
||||
private Set<IBinding> removeBindingsDefinedInIncludedHeaders(IASTTranslationUnit ast,
|
||||
Set<IBinding> bindings, IIndexFileSet reachableHeaders) throws CoreException {
|
||||
Set<IBinding> filteredBindings = new HashSet<IBinding>(bindings);
|
||||
|
@ -888,7 +761,7 @@ public class IncludeOrganizer {
|
|||
List<IPath> candidatePaths = request.getCandidatePaths();
|
||||
if (candidatePaths.size() == 1) {
|
||||
IPath path = candidatePaths.iterator().next();
|
||||
if (isPartnerFile(path)) {
|
||||
if (fContext.isPartnerFile(path)) {
|
||||
request.resolve(path);
|
||||
fContext.addHeaderToInclude(path);
|
||||
if (includedByPartner != null) {
|
||||
|
@ -1080,33 +953,6 @@ public class IncludeOrganizer {
|
|||
return headerSubstitutor.getExportingHeaders(symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given path points to a partner header of the current translation unit.
|
||||
* A header is considered a partner if its name without extension is the same as the name of
|
||||
* the translation unit, or the name of the translation unit differs by one of the suffixes
|
||||
* used for test files.
|
||||
*/
|
||||
private boolean isPartnerFile(IPath path) {
|
||||
String headerName = path.removeFileExtension().lastSegment();
|
||||
String sourceName = fContext.getTranslationUnit().getLocation().removeFileExtension().lastSegment();
|
||||
if (headerName.equals(sourceName))
|
||||
return true;
|
||||
if (sourceName.startsWith(headerName)) {
|
||||
int pos = headerName.length();
|
||||
while (pos < sourceName.length() && !Character.isLetterOrDigit(sourceName.charAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
if (pos == sourceName.length())
|
||||
return true;
|
||||
String suffix = sourceName.substring(pos);
|
||||
for (String s : fContext.getPreferences().partnerFileSuffixes) {
|
||||
if (suffix.equalsIgnoreCase(s))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<InclusionRequest> createInclusionRequests(IASTTranslationUnit ast,
|
||||
Set<IBinding> bindingsToDefine, boolean allowDeclarations,
|
||||
IIndexFileSet reachableHeaders) throws CoreException {
|
||||
|
@ -1202,7 +1048,7 @@ public class IncludeOrganizer {
|
|||
private String createIncludeDirective(IncludePrototype include, String lineComment) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
// Unresolved includes are preserved out of caution.
|
||||
if (!include.required && include.header != null) {
|
||||
if (!include.isRequired() && include.getHeader() != null) {
|
||||
switch (fContext.getPreferences().unusedStatementsDisposition) {
|
||||
case REMOVE:
|
||||
return null;
|
||||
|
@ -1214,7 +1060,7 @@ public class IncludeOrganizer {
|
|||
}
|
||||
}
|
||||
buf.append("#include "); //$NON-NLS-1$
|
||||
buf.append(include.includeInfo.toString());
|
||||
buf.append(include.getIncludeInfo().toString());
|
||||
buf.append(lineComment);
|
||||
return buf.toString();
|
||||
}
|
||||
|
|
|
@ -10,11 +10,16 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.refactoring.includes;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeEndOffset;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeOffset;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.content.IContentType;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexFileLocation;
|
||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
|
@ -65,4 +70,9 @@ public class IncludeUtil {
|
|||
public static String getPath(IIndexFileLocation fileLocation) {
|
||||
return IndexLocationFactory.getAbsolutePath(fileLocation).toOSString();
|
||||
}
|
||||
|
||||
public static boolean isContainedInRegion(IASTNode node, IRegion region) {
|
||||
return getNodeOffset(node) >= region.getOffset()
|
||||
&& getNodeEndOffset(node) <= region.getOffset() + region.getLength();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.eclipse.ui.XMLMemento;
|
|||
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
|
||||
/**
|
||||
* A set of header file substitution rules.
|
||||
*/
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package org.eclipse.cdt.internal.ui.wizards.classwizard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -63,13 +64,18 @@ import org.eclipse.cdt.ui.CUIPlugin;
|
|||
import org.eclipse.cdt.ui.CodeGeneration;
|
||||
import org.eclipse.cdt.utils.PathUtil;
|
||||
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.InclusionContext;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility;
|
||||
import org.eclipse.cdt.internal.corext.codemanipulation.StyledInclude;
|
||||
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||
import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
|
||||
import org.eclipse.cdt.internal.corext.util.Strings;
|
||||
import org.eclipse.cdt.internal.formatter.scanner.Scanner;
|
||||
import org.eclipse.cdt.internal.formatter.scanner.Token;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
|
||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences;
|
||||
import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator;
|
||||
|
||||
public class NewClassCodeGenerator {
|
||||
|
@ -703,7 +709,6 @@ public class NewClassCodeGenerator {
|
|||
ICProject cProject = headerTU.getCProject();
|
||||
IProject project = cProject.getProject();
|
||||
IPath projectLocation = new Path(project.getLocationURI().getPath());
|
||||
IPath headerLocation = new Path(headerTU.getResource().getLocationURI().getPath());
|
||||
|
||||
List<IPath> includePaths = getIncludePaths(headerTU);
|
||||
List<IPath> baseClassPaths = getBaseClassPaths(verifyBaseClasses());
|
||||
|
@ -716,52 +721,36 @@ public class NewClassCodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
List<IPath> systemIncludes = new ArrayList<IPath>();
|
||||
List<IPath> localIncludes = new ArrayList<IPath>();
|
||||
|
||||
// Sort the include paths into system and local
|
||||
InclusionContext inclusionContext = new InclusionContext(headerTU);
|
||||
List<StyledInclude> includes = new ArrayList<StyledInclude>();
|
||||
for (IPath baseClassLocation : baseClassPaths) {
|
||||
boolean isSystemIncludePath = false;
|
||||
IncludeInfo includeInfo = inclusionContext.getIncludeForHeaderFile(baseClassLocation);
|
||||
if (includeInfo != null) {
|
||||
IncludeGroupStyle style = inclusionContext.getIncludeStyle(includeInfo);
|
||||
includes.add(new StyledInclude(baseClassLocation, includeInfo, style));
|
||||
}
|
||||
}
|
||||
Collections.sort(includes);
|
||||
|
||||
IPath includePath = PathUtil.makeRelativePathToProjectIncludes(baseClassLocation, project);
|
||||
if (includePath != null && !projectLocation.isPrefixOf(baseClassLocation)) {
|
||||
isSystemIncludePath = true;
|
||||
} else if (projectLocation.isPrefixOf(baseClassLocation)
|
||||
&& projectLocation.isPrefixOf(headerLocation)) {
|
||||
includePath = PathUtil.makeRelativePath(baseClassLocation, headerLocation.removeLastSegments(1));
|
||||
}
|
||||
if (includePath == null)
|
||||
includePath = baseClassLocation;
|
||||
|
||||
// Make the new #include path in the source file only point to a relative file
|
||||
// (i.e. now that the path has been included above in the project)
|
||||
includePath = includePath.removeFirstSegments(includePath.segmentCount() - 1).setDevice(null);
|
||||
|
||||
if (isSystemIncludePath)
|
||||
systemIncludes.add(includePath);
|
||||
else
|
||||
localIncludes.add(includePath);
|
||||
}
|
||||
|
||||
StringBuilder text = new StringBuilder();
|
||||
// Write the system include paths, e.g. #include <header.h>
|
||||
for (IPath includePath : systemIncludes) {
|
||||
if (!(headerTU.getElementName().equals(includePath.toString()))) {
|
||||
String include = getIncludeString(includePath.toString(), true);
|
||||
text.append(include);
|
||||
text.append(lineDelimiter);
|
||||
IncludePreferences preferences = inclusionContext.getPreferences();
|
||||
IncludeGroupStyle previousParentStyle = null;
|
||||
for (StyledInclude include : includes) {
|
||||
IncludeGroupStyle style = include.getStyle();
|
||||
IncludeGroupStyle groupingStyle = style.getGroupingStyle(preferences.includeStyles);
|
||||
IncludeGroupStyle parentStyle = groupingStyle.getParentStyle(preferences.includeStyles);
|
||||
if (groupingStyle.isBlankLineBefore() ||
|
||||
(parentStyle != null && previousParentStyle != null &&
|
||||
parentStyle != previousParentStyle && parentStyle.isKeepTogether() &&
|
||||
parentStyle.isBlankLineBefore())) {
|
||||
text.append(lineDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the local include paths, e.g. #include "header.h"
|
||||
for (IPath includePath : localIncludes) {
|
||||
if (!(headerTU.getElementName().equals(includePath.toString()))) {
|
||||
String include = getIncludeString(includePath.toString(), false);
|
||||
text.append(include);
|
||||
text.append(lineDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
text.append("#include "); //$NON-NLS-1$
|
||||
text.append(include.getIncludeInfo().toString());
|
||||
text.append(lineDelimiter);
|
||||
previousParentStyle = parentStyle;
|
||||
}
|
||||
|
||||
monitor.done();
|
||||
return text.toString();
|
||||
}
|
||||
|
@ -1089,24 +1078,15 @@ public class NewClassCodeGenerator {
|
|||
|
||||
private String getHeaderIncludeString(ITranslationUnit sourceTU, ITranslationUnit headerTU,
|
||||
IProgressMonitor monitor) {
|
||||
IProject project = headerTU.getCProject().getProject();
|
||||
IPath projectLocation = new Path(project.getLocationURI().getPath());
|
||||
IPath headerLocation = new Path(headerTU.getResource().getLocationURI().getPath());
|
||||
IPath sourceLocation = new Path(sourceTU.getResource().getLocationURI().getPath());
|
||||
|
||||
IPath includePath = PathUtil.makeRelativePathToProjectIncludes(headerLocation, project);
|
||||
boolean isSystemIncludePath = false;
|
||||
if (headerTU.getResource() == null && includePath != null
|
||||
&& !projectLocation.isPrefixOf(headerLocation)) {
|
||||
isSystemIncludePath = true;
|
||||
} else if (projectLocation.isPrefixOf(headerLocation)
|
||||
&& projectLocation.isPrefixOf(sourceLocation)) {
|
||||
includePath = PathUtil.makeRelativePath(headerLocation, sourceLocation.removeLastSegments(1));
|
||||
InclusionContext inclusionContext = new InclusionContext(sourceTU);
|
||||
IncludeInfo includeInfo = inclusionContext.getIncludeForHeaderFile(headerLocation);
|
||||
if (includeInfo == null) {
|
||||
includeInfo = new IncludeInfo(headerLocation.toString(), false);
|
||||
}
|
||||
if (includePath == null)
|
||||
includePath = headerLocation;
|
||||
|
||||
return getIncludeString(includePath.toString(), isSystemIncludePath);
|
||||
|
||||
return "#include " + includeInfo.toString(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private boolean hasInclude(String contents, String include) {
|
||||
|
@ -1208,21 +1188,6 @@ public class NewClassCodeGenerator {
|
|||
return text.toString();
|
||||
}
|
||||
|
||||
private String getIncludeString(String fileName, boolean isSystemInclude) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("#include "); //$NON-NLS-1$
|
||||
if (isSystemInclude)
|
||||
buf.append('<');
|
||||
else
|
||||
buf.append('\"');
|
||||
buf.append(fileName);
|
||||
if (isSystemInclude)
|
||||
buf.append('>');
|
||||
else
|
||||
buf.append('\"');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private int findLastLineChar(String contents, int startPos) {
|
||||
int endPos = contents.length() - 1;
|
||||
int linePos = startPos;
|
||||
|
|
Loading…
Add table
Reference in a new issue