diff options
author | Sergey Prigogin | 2013-08-08 03:30:39 +0000 |
---|---|---|
committer | Sergey Prigogin | 2013-08-08 03:35:59 +0000 |
commit | b042de243aa603e14700ba95ac8d6fe34291a9d6 (patch) | |
tree | f16d33500975f3d0fe46218a2653600953bfb00a | |
parent | e2ef1d3d9fbec73ee72989a9302b53d6635439cc (diff) | |
download | org.eclipse.cdt-b042de243aa603e14700ba95ac8d6fe34291a9d6.tar.gz org.eclipse.cdt-b042de243aa603e14700ba95ac8d6fe34291a9d6.tar.xz org.eclipse.cdt-b042de243aa603e14700ba95ac8d6fe34291a9d6.zip |
Bug 414624. First step towards code reuse between Add Include and
Organize Includes commands.
4 files changed, 65 insertions, 151 deletions
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/AddIncludesOperation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/AddIncludesOperation.java index 8df7383de33..86267ecb2c5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/AddIncludesOperation.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/AddIncludesOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation 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 @@ -34,9 +34,9 @@ import org.eclipse.cdt.core.model.IMacro; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.ui.IRequiredInclude; 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. @@ -45,8 +45,8 @@ import org.eclipse.cdt.internal.ui.editor.CEditorMessages; public class AddIncludesOperation implements IWorkspaceRunnable { private final ITranslationUnit fTranslationUnit; private final int fBeforeOffset; - private final IRequiredInclude[] fIncludes; - private final String[] fUsings; + private final List<IncludeInfo> fIncludes; + private final List<String> fUsings; private String fNewLine; private IBuffer fBuffer; private List<ICElement> fExistingIncludes; @@ -61,8 +61,8 @@ public class AddIncludesOperation implements IWorkspaceRunnable { * @param includes '#include' statements to insert. * @param usings 'using' statements to insert. */ - public AddIncludesOperation(ITranslationUnit tu, int beforeOffset, IRequiredInclude[] includes, - String[] usings) { + public AddIncludesOperation(ITranslationUnit tu, int beforeOffset, List<IncludeInfo> includes, + List<String> usings) { fTranslationUnit = tu; fBeforeOffset = beforeOffset; fIncludes= includes; @@ -89,7 +89,7 @@ public class AddIncludesOperation implements IWorkspaceRunnable { fExistingIncludes = fTranslationUnit.getChildrenOfType(ICElement.C_INCLUDE); fIncludesInsert = getIncludesInsert(); monitor.worked(1); - if (fUsings != null && fUsings.length > 0) { + if (!fUsings.isEmpty()) { fExistingUsings = fTranslationUnit.getChildrenOfType(ICElement.C_USING); } fUsingsInsert = getUsingsInsert(); @@ -112,13 +112,13 @@ public class AddIncludesOperation implements IWorkspaceRunnable { } private InsertEdit getIncludesInsert() throws CoreException { - if (fIncludes == null || fIncludes.length == 0) { + if (fIncludes.isEmpty()) { return null; } - ArrayList<IRequiredInclude> toAdd = new ArrayList<IRequiredInclude>(); - for (IRequiredInclude include : fIncludes) { - String name = include.getIncludeName(); + ArrayList<IncludeInfo> toAdd = new ArrayList<IncludeInfo>(); + for (IncludeInfo include : fIncludes) { + String name = include.getName(); boolean found = false; for (ICElement element : fExistingIncludes) { ISourceRange range = ((ISourceReference) element).getSourceRange(); @@ -140,12 +140,8 @@ public class AddIncludesOperation implements IWorkspaceRunnable { // So we have our list. Now insert. StringBuilder buf = new StringBuilder(); - for (IRequiredInclude include : toAdd) { - if (include.isStandard()) { - buf.append("#include <" + include.getIncludeName() + ">").append(fNewLine); //$NON-NLS-1$ //$NON-NLS-2$ - } else { - buf.append("#include \"" + include.getIncludeName() + "\"").append(fNewLine); //$NON-NLS-1$ //$NON-NLS-2$ - } + for (IncludeInfo include : toAdd) { + buf.append("#include ").append(include.toString()).append(fNewLine); //$NON-NLS-1$ } int pos= getIncludeInsertionPosition(); @@ -164,11 +160,11 @@ public class AddIncludesOperation implements IWorkspaceRunnable { } private InsertEdit getUsingsInsert() throws CoreException { - if (fUsings == null || fUsings.length == 0) { + if (fUsings.isEmpty()) { return null; } - ArrayList<String> toAdd = new ArrayList<String>(fUsings.length); + ArrayList<String> toAdd = new ArrayList<String>(fUsings.size()); for (String name : fUsings) { boolean found = false; for (ICElement element : fExistingUsings) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java index 6ca570e5744..b6ffa3337fc 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation 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 @@ -13,8 +13,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.editor; -import java.io.File; -import java.io.IOException; +import static org.eclipse.cdt.core.index.IndexLocationFactory.getAbsolutePath; + import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.ArrayDeque; @@ -32,7 +32,6 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.operation.IRunnableWithProgress; @@ -77,15 +76,12 @@ import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.core.parser.IScannerInfo; -import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.IFunctionSummary; import org.eclipse.cdt.ui.IRequiredInclude; import org.eclipse.cdt.ui.text.ICHelpInvocationContext; import org.eclipse.cdt.ui.text.SharedASTJob; -import org.eclipse.cdt.utils.PathUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; @@ -95,6 +91,8 @@ import org.eclipse.cdt.internal.corext.codemanipulation.AddIncludesOperation; 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; /** @@ -106,9 +104,9 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { private ITranslationUnit fTu; private IProject fProject; - private String[] fIncludePath; - private IRequiredInclude[] fRequiredIncludes; - private String[] fUsingDeclarations; + private final List<IncludeInfo> fRequiredIncludes = new ArrayList<IncludeInfo>(); + private final List<String> fUsingDeclarations = new ArrayList<String>(); + protected InclusionContext fContext; public AddIncludeOnSelectionAction(ITextEditor editor) { super(CEditorMessages.getBundleForConstructedKeys(), "AddIncludeOnSelection.", editor); //$NON-NLS-1$ @@ -117,7 +115,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { ICHelpContextIds.ADD_INCLUDE_ON_SELECTION_ACTION); } - private void insertInclude(IRequiredInclude[] includes, String[] usings, int beforeOffset) { + private void insertInclude(List<IncludeInfo> includes, List<String> usings, int beforeOffset) { AddIncludesOperation op= new AddIncludesOperation(fTu, beforeOffset, includes, usings); try { PlatformUI.getWorkbench().getProgressService().runInUI( @@ -149,17 +147,6 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { return; } fProject = fTu.getCProject().getProject(); - IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(fProject); - fIncludePath = null; - if (provider != null) { - IScannerInfo info = provider.getScannerInformation(fTu.getResource()); - if (info != null) { - fIncludePath = info.getIncludePaths(); - } - } - if (fIncludePath == null) { - fIncludePath = new String[0]; - } try { final ISelection selection= getTextEditor().getSelectionProvider().getSelection(); @@ -182,19 +169,24 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { job.schedule(); job.join(); - if (fRequiredIncludes == null || fRequiredIncludes.length == 0 && lookupName[0].length() > 0) { - // Try contribution from plugins. + if (fRequiredIncludes.isEmpty() && lookupName[0].length() > 0) { + // Try contribution from plug-ins. IFunctionSummary fs = findContribution(lookupName[0]); if (fs != null) { - fRequiredIncludes = fs.getIncludes(); + IRequiredInclude[] functionIncludes = fs.getIncludes(); + if (functionIncludes != null) { + for (IRequiredInclude include : functionIncludes) { + fRequiredIncludes.add(new IncludeInfo(include.getIncludeName(), include.isStandard())); + } + } String ns = fs.getNamespace(); if (ns != null && ns.length() > 0) { - fUsingDeclarations = new String[] { fs.getNamespace() }; + fUsingDeclarations.add(fs.getNamespace()); } } } - if (fRequiredIncludes != null && fRequiredIncludes.length >= 0) { + if (!fRequiredIncludes.isEmpty()) { insertInclude(fRequiredIncludes, fUsingDeclarations, ((ITextSelection) selection).getOffset()); } } catch (InterruptedException e) { @@ -213,6 +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); IASTNodeSelector selector = ast.getNodeSelector(fTu.getLocation().toOSString()); IASTName name = selector.findEnclosingName(selection.getOffset(), selection.getLength()); if (name == null) { @@ -298,18 +291,18 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { }); } - fRequiredIncludes = null; - fUsingDeclarations = null; + fRequiredIncludes.clear(); + fUsingDeclarations.clear(); if (candidates.size() == 1) { IncludeCandidate candidate = candidates.get(0); - fRequiredIncludes = new IRequiredInclude[] { candidate.getInclude() }; + fRequiredIncludes.add(candidate.getInclude()); IIndexBinding indexBinding = candidate.getBinding(); if (indexBinding instanceof ICPPBinding && !(indexBinding instanceof IIndexMacro)) { // Decide what 'using' declaration, if any, should be added along with the include. String usingDeclaration = deduceUsingDeclaration(binding, indexBinding, ast); if (usingDeclaration != null) - fUsingDeclarations = new String[] { usingDeclaration }; + fUsingDeclarations.add(usingDeclaration); } } } @@ -328,7 +321,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { // or a source file that was already included by some other file. if (!isSource(getPath(file)) || index.findIncludedBy(file, 0).length > 0) { IIndexFile representativeFile = getRepresentativeFile(file, index); - IRequiredInclude include = getRequiredInclude(representativeFile, index); + IncludeInfo include = getRequiredInclude(representativeFile, index); if (include != null) { IncludeCandidate candidate = new IncludeCandidate(binding, include); if (!candidates.containsKey(candidate.toString())) { @@ -550,9 +543,8 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { * @return the required include * @throws CoreException */ - private IRequiredInclude getRequiredInclude(IIndexFile file, IIndex index) throws CoreException { - IIndexInclude[] includes; - includes = index.findIncludedBy(file); + private IncludeInfo getRequiredInclude(IIndexFile file, IIndex index) throws CoreException { + IIndexInclude[] includes = index.findIncludedBy(file); if (includes.length > 0) { // Let the existing includes vote. To be eligible to vote, an include // has to be resolvable in the context of the current translation unit. @@ -560,7 +552,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { String[] ballotBox = new String[includes.length]; int k = 0; for (IIndexInclude include : includes) { - if (isResolvable(include)) { + if (isResolvableInCurrentContext(include)) { ballotBox[k++] = include.getFullName(); if (include.isSystemInclude()) { systemIncludeVotes++; @@ -584,65 +576,26 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { winnerVotes = votes; } } - return new RequiredInclude(winner, systemIncludeVotes * 2 >= k); + return new IncludeInfo(winner, systemIncludeVotes * 2 >= k); } } // The file has never been included before. - URI targetUri = file.getLocation().getURI(); - IPath targetLocation = PathUtil.getCanonicalPath(new Path(targetUri.getPath())); - IPath sourceLocation = PathUtil.getCanonicalPath(fTu.getResource().getLocation()); - boolean isSystemIncludePath = false; - - IPath path = PathUtil.makeRelativePathToIncludes(targetLocation, fIncludePath); - if (path != null && ResourceLookup.findFilesForLocationURI(targetUri).length == 0) { - // A header file in the include path but outside the workspace is included with angle brackets. - isSystemIncludePath = true; - } - if (path == null) { - IPath sourceDirectory = sourceLocation.removeLastSegments(1); - if (PathUtil.isPrefix(sourceDirectory, targetLocation)) { - path = targetLocation.removeFirstSegments(sourceDirectory.segmentCount()); - } else { - path = targetLocation; - } - if (targetLocation.getDevice() != null && - targetLocation.getDevice().equalsIgnoreCase(sourceDirectory.getDevice())) { - path = path.setDevice(null); - } - if (path.isAbsolute() && path.getDevice() == null && - ResourceLookup.findFilesForLocationURI(targetUri).length != 0) { - // The file is inside workspace. Include with a relative path. - path = PathUtil.makeRelativePath(path, sourceDirectory); - } - } - return new RequiredInclude(path.toString(), isSystemIncludePath); + IPath targetLocation = getAbsolutePath(file.getLocation()); + return fContext.getIncludeForHeaderFile(targetLocation); } /** - * Returns <code>true</code> if the given include can be resolved in the context of + * Returns {@code true} if the given include can be resolved in the context of * the current translation unit. */ - private boolean isResolvable(IIndexInclude include) { + private boolean isResolvableInCurrentContext(IIndexInclude include) { try { - File target = new File(include.getIncludesLocation().getURI().getPath()); - String includeName = include.getFullName(); - for (String dir : fIncludePath) { - if (target.equals(new File(dir, includeName))) { - return true; - } - } - if (include.isSystemInclude()) { - return false; - } - String directory = new File(fTu.getLocationURI().getPath()).getParent(); - return target.equals(new File(directory, includeName).getCanonicalFile()); + IncludeInfo includeInfo = new IncludeInfo(include.getFullName(), include.isSystemInclude()); + return fContext.resolveInclude(includeInfo) != null; } catch (CoreException e) { CUIPlugin.log(e); return false; - } catch (IOException e) { - CUIPlugin.log(e); - return false; } } @@ -671,10 +624,10 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { */ private static class IncludeCandidate { private final IIndexBinding binding; - private final IRequiredInclude include; + private final IncludeInfo include; private final String label; - public IncludeCandidate(IIndexBinding binding, IRequiredInclude include) throws CoreException { + public IncludeCandidate(IIndexBinding binding, IncludeInfo include) throws CoreException { this.binding = binding; this.include = include; this.label = getBindingQualifiedName(binding) + " - " + include.toString(); //$NON-NLS-1$ @@ -684,7 +637,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { return binding; } - public IRequiredInclude getInclude() { + public IncludeInfo getInclude() { return include; } @@ -693,39 +646,4 @@ public class AddIncludeOnSelectionAction extends TextEditorAction { return label; } } - - private static class RequiredInclude implements IRequiredInclude { - final String includeName; - final boolean isSystem; - - RequiredInclude(String includeName, boolean isSystem) { - this.includeName = includeName; - this.isSystem = isSystem; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.ui.IRequiredInclude#getIncludeName() - */ - @Override - public String getIncludeName() { - return includeName; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.ui.IRequiredInclude#isStandard() - */ - @Override - public boolean isStandard() { - return isSystem; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(includeName.length() + 2); - buf.append(isSystem ? '<' : '"'); - buf.append(includeName); - buf.append(isSystem ? '>' : '"'); - return buf.toString(); - } - } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java index 90ca609a1dc..e5decf5150c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.includes; +import static org.eclipse.cdt.core.index.IndexLocationFactory.getAbsolutePath; import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getEndingLineNumber; import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeEndOffset; import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeOffset; @@ -72,11 +73,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexFile; -import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexInclude; import org.eclipse.cdt.core.index.IIndexName; -import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.CharArrayIntMap; @@ -866,13 +865,13 @@ public class IncludeOrganizer { protected boolean isSatisfiedByIncludedHeaders(InclusionRequest request, Set<IPath> includedHeaders) throws CoreException { for (IIndexFile file : request.getDeclaringFiles().keySet()) { - IPath path = getPath(file.getLocation()); + IPath path = getAbsolutePath(file.getLocation()); if (includedHeaders.contains(path)) return true; IIndexInclude[] includedBy = fContext.getIndex().findIncludedBy(file, IIndex.DEPTH_INFINITE); for (IIndexInclude include : includedBy) { - path = getPath(include.getIncludedByLocation()); + path = getAbsolutePath(include.getIncludedByLocation()); if (includedHeaders.contains(path)) return true; } @@ -897,7 +896,7 @@ public class IncludeOrganizer { IIndexFile indexFile = request.getDeclaringFiles().keySet().iterator().next(); if (!includedByPartner.contains(indexFile)) { for (IIndexInclude include : indexFile.getIncludes()) { - fContext.addHeaderAlreadyIncluded(getPath(include.getIncludesLocation())); + fContext.addHeaderAlreadyIncluded(getAbsolutePath(include.getIncludesLocation())); } includedByPartner.add(indexFile); } @@ -1081,10 +1080,6 @@ public class IncludeOrganizer { return headerSubstitutor.getExportingHeaders(symbol); } - private static IPath getPath(IIndexFileLocation location) { - return IndexLocationFactory.getAbsolutePath(location); - } - /** * 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 @@ -1159,7 +1154,7 @@ public class IncludeOrganizer { // Don't include it. continue; } - IPath path = getPath(indexFile.getLocation()); + IPath path = getAbsolutePath(indexFile.getLocation()); declaringHeaders.put(indexFile, path); if (reachableHeaders.contains(indexFile)) reachableDeclaringHeaders.put(indexFile, path); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/InclusionContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/InclusionContext.java index d64e0595a8b..18a7c731784 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/InclusionContext.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/InclusionContext.java @@ -147,8 +147,13 @@ public class InclusionContext { isSystem = !pathElement.isForQuoteIncludesOnly(); } } - if (shortestInclude == null) - return null; + if (shortestInclude == null) { + if (fIncludeSearchPath.isInhibitUseOfCurrentFileDirectory() || + !fCurrentDirectory.isPrefixOf(fullPath)) { + return null; + } + shortestInclude = fullPath.removeFirstSegments(fCurrentDirectory.segmentCount()).toString(); + } include = new IncludeInfo(shortestInclude, isSystem); // Don't put an include to fullPath to fIncludeResolutionCache since it may be wrong // if the header was included by #include_next. |