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