1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-30 20:35:38 +02:00

Extensive rewrite of Add Include. Bugs 236530 and 255952.

This commit is contained in:
Sergey Prigogin 2009-05-04 21:28:23 +00:00
parent 1580548a45
commit deeb5db9ae
8 changed files with 691 additions and 388 deletions

View file

@ -29,6 +29,7 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.parser.ParserMessages;
import org.eclipse.core.runtime.PlatformObject;
@ -230,7 +231,7 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
}
public IBinding getOwner() throws DOMException {
return null;
return node instanceof IASTName ? CPPVisitor.findNameOwner((IASTName) node, true) : null;
}
public void setASTNode(IASTName name) {

View file

@ -2010,10 +2010,17 @@ public class CPPVisitor extends ASTQueries {
while (node instanceof IASTName) {
if (node instanceof ICPPASTQualifiedName) {
IASTName[] qn= ((ICPPASTQualifiedName) node).getNames();
if (qn.length < 2)
return null;
return qn[qn.length - 2].resolveBinding();
int i = qn.length;
while (--i >= 0) {
if (qn[i] == name) {
break;
}
}
if (--i < 0)
break;
return qn[i].resolveBinding();
}
name = (IASTName) node;
node= node.getParent();
}
return findDeclarationOwner(node, allowFunction);

View file

@ -9,6 +9,7 @@
* QNX Software Systems - initial API and implementation
* Markus Schorn (Wind River Systems)
* Ed Swartz (Nokia)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.utils;
@ -23,6 +24,7 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
@ -65,8 +67,8 @@ public class PathUtil {
IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
if (workspaceRoot != null) {
IPath workspaceLocation = workspaceRoot.getLocation();
if (workspaceLocation != null && workspaceLocation.isPrefixOf(fullPath)) {
int segments = fullPath.matchingFirstSegments(workspaceLocation);
if (workspaceLocation != null && isPrefix(workspaceLocation, fullPath)) {
int segments = matchingFirstSegments(fullPath, workspaceLocation);
IPath relPath = fullPath.setDevice(null).removeFirstSegments(segments);
return new Path("").addTrailingSeparator().append(relPath); //$NON-NLS-1$
}
@ -76,11 +78,11 @@ public class PathUtil {
public static IPath getProjectRelativePath(IPath fullPath, IProject project) {
IPath projectPath = project.getFullPath();
if (projectPath.isPrefixOf(fullPath)) {
if (isPrefix(projectPath, fullPath)) {
return fullPath.removeFirstSegments(projectPath.segmentCount());
}
projectPath = project.getLocation();
if (projectPath.isPrefixOf(fullPath)) {
if (isPrefix(projectPath, fullPath)) {
return fullPath.removeFirstSegments(projectPath.segmentCount());
}
return getWorkspaceRelativePath(fullPath);
@ -94,7 +96,7 @@ public class PathUtil {
IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
if (workspaceRoot != null && wsRelativePath != null) {
IPath workspaceLocation = workspaceRoot.getLocation();
if (workspaceLocation != null && !workspaceLocation.isPrefixOf(wsRelativePath)) {
if (workspaceLocation != null && !isPrefix(workspaceLocation, wsRelativePath)) {
return workspaceLocation.append(wsRelativePath);
}
}
@ -102,7 +104,7 @@ public class PathUtil {
}
public static IPath makeRelativePath(IPath path, IPath relativeTo) {
int segments = relativeTo.matchingFirstSegments(path);
int segments = matchingFirstSegments(relativeTo, path);
if (segments > 0) {
IPath prefix = relativeTo.removeFirstSegments(segments);
IPath suffix = path.removeFirstSegments(segments);
@ -131,8 +133,8 @@ public class PathUtil {
int mostSegments = 0;
for (int i = 0; i < includePaths.length; ++i) {
IPath includePath = new Path(includePaths[i]);
if (includePath.isPrefixOf(fullPath)) {
int segments = includePath.matchingFirstSegments(fullPath);
if (isPrefix(includePath, fullPath)) {
int segments = includePath.segmentCount();
if (segments > mostSegments) {
relativePath = fullPath.removeFirstSegments(segments).setDevice(null);
mostSegments = segments;
@ -171,4 +173,104 @@ public class PathUtil {
}
return null;
}
/**
* Checks whether path1 is the same as path2.
* @return <code>true</code> if path1 is the same as path2, and <code>false</code> otherwise
*
* Similar to IPath.equals(Object obj), but takes case sensitivity of the file system
* into account.
* @since 5.1
*/
public boolean equal(IPath path1, IPath path2) {
// Check leading separators
if (path1.isAbsolute() != path2.isAbsolute() || path1.isUNC() != path2.isUNC()) {
return false;
}
int i = path1.segmentCount();
// Check segment count
if (i != path2.segmentCount())
return false;
// Check segments in reverse order - later segments more likely to differ
while (--i >= 0) {
if (!path1.segment(i).equals(path2.segment(i)))
return false;
}
// Check device last (least likely to differ)
if (path1.getDevice() == null) {
return path2.getDevice() == null;
} else {
return path1.getDevice().equalsIgnoreCase(path2.getDevice());
}
}
/**
* Checks whether path1 is a prefix of path2. To be a prefix, path1's segments
* must appear in path1 in the same order, and their device ids must match.
* <p>
* An empty path is a prefix of all paths with the same device; a root path is a prefix of
* all absolute paths with the same device.
* </p>
* @return <code>true</code> if path1 is a prefix of path2, and <code>false</code> otherwise
*
* Similar to IPath.isPrefixOf(IPath anotherPath), but takes case sensitivity of the file system
* into account.
* @since 5.1
*/
public static boolean isPrefix(IPath path1, IPath path2) {
if (path1.getDevice() == null) {
if (path2.getDevice() != null) {
return false;
}
} else {
if (!path1.getDevice().equalsIgnoreCase(path2.getDevice())) {
return false;
}
}
if (path1.isEmpty() || (path1.isRoot() && path2.isAbsolute())) {
return true;
}
int len1 = path1.segmentCount();
if (len1 > path2.segmentCount()) {
return false;
}
boolean caseSensitive = !isWindowsFileSystem();
for (int i = 0; i < len1; i++) {
if (!(caseSensitive ?
path1.segment(i).equals(path2.segment(i)) :
path1.segment(i).equalsIgnoreCase(path2.segment(i)))) {
return false;
}
}
return true;
}
/**
* Returns the number of segments which match in path1 and path2
* (device ids are ignored), comparing in increasing segment number order.
*
* @return the number of matching segments
* Similar to IPath.matchingFirstSegments(IPath anotherPath), but takes case sensitivity
* of the file system into account.
* @since 5.1
*/
public static int matchingFirstSegments(IPath path1, IPath path2) {
Assert.isNotNull(path1);
Assert.isNotNull(path2);
int len1 = path1.segmentCount();
int len2 = path2.segmentCount();
int max = Math.min(len1, len2);
int count = 0;
boolean caseSensitive = !isWindowsFileSystem();
for (int i = 0; i < max; i++) {
if (!(caseSensitive ?
path1.segment(i).equals(path2.segment(i)) :
path1.segment(i).equalsIgnoreCase(path2.segment(i)))) {
return count;
}
count++;
}
return count;
}
}

View file

@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* QNX Software Systems
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.corext.codemanipulation;
@ -24,6 +25,8 @@ import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.IBuffer;
@ -43,26 +46,27 @@ import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
* If the translation unit is open in an editor, be sure to pass over its working copy.
*/
public class AddIncludesOperation implements IWorkspaceRunnable {
private ITranslationUnit fTranslationUnit;
private IRequiredInclude[] fIncludes;
private String[] fUsings;
private final String fNewLine;
private IRegion insertedIncludes;
/**
* Generate include statements for the passed java elements
*/
public AddIncludesOperation(ITranslationUnit tu, IRequiredInclude[] includes, boolean save) {
this (tu, includes, null, save);
this(tu, includes, null, save);
}
/**
* Generate include statements for the passed c elements
*/
public AddIncludesOperation(ITranslationUnit tu, IRequiredInclude[] includes, String[] using, boolean save) {
public AddIncludesOperation(ITranslationUnit tu, IRequiredInclude[] includes, String[] usings,
boolean save) {
super();
fIncludes= includes;
fUsings = using;
fUsings = usings;
fTranslationUnit = tu;
fNewLine= getNewLine(tu);
}
@ -82,10 +86,10 @@ public class AddIncludesOperation implements IWorkspaceRunnable {
} catch (CModelException e) {
} catch (BadLocationException e) {
}
return System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$ }
return System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
}
public void executeIncludes(IProgressMonitor monitor) throws CoreException {
private void insertIncludes(IProgressMonitor monitor) throws CoreException {
// Sanity
if (fIncludes == null || fIncludes.length == 0) {
return;
@ -96,122 +100,118 @@ public class AddIncludesOperation implements IWorkspaceRunnable {
monitor.beginTask(CEditorMessages.AddIncludesOperation_description, 2);
List<?> elements = fTranslationUnit.getChildrenOfType(ICElement.C_INCLUDE);
for (int i = 0; i < fIncludes.length; ++i) {
String name = fIncludes[i].getIncludeName();
List<ICElement> elements = fTranslationUnit.getChildrenOfType(ICElement.C_INCLUDE);
for (IRequiredInclude include : fIncludes) {
String name = include.getIncludeName();
boolean found = false;
for (int j = 0; j < elements.size(); ++j) {
IInclude include = (IInclude)elements.get(j);
if (name.equals(include.getElementName())) {
for (ICElement element : elements) {
if (name.equals(element.getElementName())) {
found = true;
break;
}
}
if (!found) {
toAdd.add(fIncludes[i]);
toAdd.add(include);
}
}
if (toAdd.size() > 0) {
if (!toAdd.isEmpty()) {
// So we have our list. Now insert.
StringBuffer insert = new StringBuffer(""); //$NON-NLS-1$
for(int j = 0; j < toAdd.size(); j++) {
IRequiredInclude req = toAdd.get(j);
if (req.isStandard()) {
insert.append("#include <" + req.getIncludeName() + ">").append(fNewLine); //$NON-NLS-1$ //$NON-NLS-2$
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 {
insert.append("#include \"" + req.getIncludeName() + "\"").append(fNewLine); //$NON-NLS-1$ //$NON-NLS-2$
buf.append("#include \"" + include.getIncludeName() + "\"").append(fNewLine); //$NON-NLS-1$ //$NON-NLS-2$
}
}
int pos;
if (elements.size() > 0) {
IInclude lastInclude = (IInclude)elements.get(elements.size() - 1);
int pos = 0;
if (!elements.isEmpty()) {
IInclude lastInclude = (IInclude) elements.get(elements.size() - 1);
ISourceRange range = lastInclude.getSourceRange();
pos = range.getStartPos() + range.getLength();
} else {
pos = 0;
}
monitor.worked(1);
replace(pos, insert.toString());
replace(pos, buf.toString());
insertedIncludes = new Region(pos, buf.length());
monitor.worked(1);
}
}
}
public void executeUsings(IProgressMonitor monitor) throws CoreException {
private void insertUsings(IProgressMonitor monitor) throws CoreException {
// Sanity
if (fUsings == null || fUsings.length == 0) {
return;
}
if (fTranslationUnit != null) {
ArrayList<String> toAdd = new ArrayList<String>();
ArrayList<String> toAdd = new ArrayList<String>(fUsings.length);
monitor.beginTask(CEditorMessages.AddIncludesOperation_description, 2);
List<?> elements = fTranslationUnit.getChildrenOfType(ICElement.C_USING);
for (int i = 0; i < fUsings.length; ++i) {
String name = fUsings[i];
List<ICElement> elements = fTranslationUnit.getChildrenOfType(ICElement.C_USING);
for (String name : fUsings) {
boolean found = false;
for (int j = 0; j < elements.size(); ++j) {
IUsing using = (IUsing)elements.get(j);
if (name.equals(using.getElementName())) {
for (ICElement element : elements) {
if (name.equals(element.getElementName())) {
found = true;
break;
}
}
if (!found) {
toAdd.add(fUsings[i]);
toAdd.add(name);
}
}
if (toAdd.size() > 0) {
if (!toAdd.isEmpty()) {
// So we have our list. Now insert.
StringBuffer insert = new StringBuffer(""); //$NON-NLS-1$
for(int j = 0; j < toAdd.size(); j++) {
String using = toAdd.get(j);
insert.append("using namespace " + using + ";").append(fNewLine); //$NON-NLS-1$ //$NON-NLS-2$
StringBuilder buf = new StringBuilder();
for (String using : toAdd) {
buf.append("using ").append(using).append(';').append(fNewLine); //$NON-NLS-1$
}
int pos;
List<?> includes = fTranslationUnit.getChildrenOfType(ICElement.C_INCLUDE);
if (includes.size() > 0) {
IInclude lastInclude = (IInclude)includes.get(includes.size() - 1);
ISourceRange range = lastInclude.getSourceRange();
pos = range.getStartPos() + range.getLength();
} else if (elements.size() > 0) {
IUsing lastUsing = (IUsing)includes.get(includes.size() - 1);
int pos = 0;
if (!elements.isEmpty()) {
IUsing lastUsing = (IUsing) elements.get(elements.size() - 1);
ISourceRange range = lastUsing.getSourceRange();
pos = range.getStartPos() + range.getLength();
} else {
pos = 0;
List<ICElement> includes = fTranslationUnit.getChildrenOfType(ICElement.C_INCLUDE);
if (!includes.isEmpty()) {
IInclude lastInclude = (IInclude) includes.get(includes.size() - 1);
ISourceRange range = lastInclude.getSourceRange();
pos = range.getStartPos() + range.getLength();
}
if (!includes.isEmpty() || insertedIncludes != null) {
buf.insert(0, fNewLine);
}
}
if (insertedIncludes != null && pos >= insertedIncludes.getOffset()) {
pos += insertedIncludes.getLength();
}
monitor.worked(1);
replace(pos, insert.toString());
replace(pos, buf.toString());
monitor.worked(1);
}
}
}
void replace(int pos, String s) {
try {
IBuffer buffer = fTranslationUnit.getBuffer();
// Now find the next newline and insert after that
if (pos > 0) {
while (buffer.getChar(pos) != '\n') {
pos++;
}
if (buffer.getChar(pos) == '\r') {
pos++;
}
private void replace(int pos, String s) throws CModelException {
IBuffer buffer = fTranslationUnit.getBuffer();
// Now find the next newline and insert after that
if (pos > 0) {
while (buffer.getChar(pos) != '\n') {
pos++;
}
buffer.replace(pos, 0, s);
} catch (Exception e) {
// ignore; should we log ?
if (buffer.getChar(pos) == '\r') {
pos++;
}
pos++;
}
buffer.replace(pos, 0, s);
}
public void run(IProgressMonitor monitor) throws CoreException {
@ -219,8 +219,8 @@ public class AddIncludesOperation implements IWorkspaceRunnable {
monitor= new NullProgressMonitor();
}
try {
executeUsings(monitor);
executeIncludes(monitor);
insertIncludes(monitor);
insertUsings(monitor);
} finally {
monitor.done();
}
@ -229,7 +229,7 @@ public class AddIncludesOperation implements IWorkspaceRunnable {
/**
* @return Returns the scheduling rule for this operation
*/
public ISchedulingRule getScheduleRule() {
public ISchedulingRule getSchedulingRule() {
return ResourcesPlugin.getWorkspace().getRoot();
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
* Copyright (c) 2000, 2009 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
@ -9,341 +9,406 @@
* IBM Corporation - initial API and implementation
* QNX Software Systems
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
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.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.browser.IQualifiedTypeName;
import org.eclipse.cdt.core.browser.QualifiedTypeName;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
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.ui.CUIPlugin;
import org.eclipse.cdt.ui.IFunctionSummary;
import org.eclipse.cdt.ui.IRequiredInclude;
import org.eclipse.cdt.ui.browser.typeinfo.TypeInfoLabelProvider;
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.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.corext.codemanipulation.AddIncludesOperation;
import org.eclipse.cdt.internal.ui.CHelpProviderManager;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter;
import org.eclipse.cdt.internal.ui.text.CWordFinder;
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
// TODO this is a big TODO.
public class AddIncludeOnSelectionAction extends Action implements IUpdate {
private ITextEditor fEditor;
/**
* Adds an include statement and, optionally, a 'using' declaration for the currently
* selected name.
*/
public class AddIncludeOnSelectionAction extends TextEditorAction {
private ITranslationUnit fTu;
private IProject fProject;
private String[] fIncludePath;
private IRequiredInclude[] fRequiredIncludes;
private String[] fUsings;
class RequiredIncludes implements IRequiredInclude {
String name;
boolean isStandard;
RequiredIncludes(String n) {
name = n;
isStandard = true;
}
RequiredIncludes(String n, boolean isStandard) {
name = n;
this.isStandard = isStandard;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.ui.IRequiredInclude#getIncludeName()
*/
public String getIncludeName() {
return name;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.ui.IRequiredInclude#isStandard()
*/
public boolean isStandard() {
return isStandard;
}
}
private String[] fUsingDeclarations;
public AddIncludeOnSelectionAction(ITextEditor editor) {
super(CEditorMessages.AddIncludeOnSelection_label);
setToolTipText(CEditorMessages.AddIncludeOnSelection_tooltip);
setDescription(CEditorMessages.AddIncludeOnSelection_description);
super(CEditorMessages.getBundleForConstructedKeys(), "AddIncludeOnSelection.", editor); //$NON-NLS-1$
fEditor= editor;
CUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(this, ICHelpContextIds.ADD_INCLUDE_ON_SELECTION_ACTION);
CUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(this,
ICHelpContextIds.ADD_INCLUDE_ON_SELECTION_ACTION);
}
private void addInclude(ITranslationUnit tu) {
AddIncludesOperation op= new AddIncludesOperation(tu, fRequiredIncludes, fUsings, false);
private void insertInclude(IRequiredInclude[] includes, String[] usings) {
AddIncludesOperation op= new AddIncludesOperation(fTu, includes, usings, false);
try {
PlatformUI.getWorkbench().getProgressService().runInUI(
PlatformUI.getWorkbench().getProgressService(),
new WorkbenchRunnableAdapter(op), op.getScheduleRule());
new WorkbenchRunnableAdapter(op), op.getSchedulingRule());
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getShell(), CEditorMessages.AddIncludeOnSelection_error_message1, null);
ExceptionHandler.handle(e, getShell(), CEditorMessages.AddIncludeOnSelection_error_title,
CEditorMessages.AddIncludeOnSelection_insertion_failed);
} catch (InterruptedException e) {
// Do nothing. Operation has been canceled.
}
}
protected ITranslationUnit getTranslationUnit () {
ITranslationUnit unit = null;
if (fEditor != null) {
IEditorInput editorInput= fEditor.getEditorInput();
unit = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editorInput);
private static ITranslationUnit getTranslationUnit(ITextEditor editor) {
if (editor == null) {
return null;
}
return unit;
return CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
}
private Shell getShell() {
return fEditor.getSite().getShell();
return getTextEditor().getSite().getShell();
}
@Override
public void run() {
ITranslationUnit tu= getTranslationUnit();
if (tu == null) {
fTu = getTranslationUnit(getTextEditor());
if (fTu == null) {
return;
}
IIndex index;
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 {
index = CCorePlugin.getIndexManager().getIndex(tu.getCProject(), IIndexManager.ADD_DEPENDENCIES);
index.acquireReadLock();
try {
extractIncludes(fEditor, index);
addInclude(tu);
} finally {
index.releaseReadLock();
final ISelection selection= getTextEditor().getSelectionProvider().getSelection();
if (selection.isEmpty() || !(selection instanceof ITextSelection)) {
return;
}
if (!validateEditorInputState()) {
return;
}
final String[] lookupName = new String[1];
SharedASTJob job = new SharedASTJob(CEditorMessages.AddIncludeOnSelection_label, fTu) {
@Override
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
deduceInclude((ITextSelection) selection, ast, lookupName);
return Status.OK_STATUS;
}
};
job.schedule();
job.join();
if (fRequiredIncludes == null || fRequiredIncludes.length == 0 && lookupName[0].length() > 0) {
// Try contribution from plugins.
IFunctionSummary fs = findContribution(lookupName[0]);
if (fs != null) {
fRequiredIncludes = fs.getIncludes();
String ns = fs.getNamespace();
if (ns != null && ns.length() > 0) {
fUsingDeclarations = new String[] { fs.getNamespace() };
}
}
}
if (fRequiredIncludes != null && fRequiredIncludes.length >= 0) {
insertInclude(fRequiredIncludes, fUsingDeclarations);
}
} catch (CoreException e) {
CUIPlugin.log(e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
fUsings = null;
fRequiredIncludes = null;
}
/**
* To be used by ElementListSelectionDialog for user to choose which declarations/
* definitions for "add include" when there are more than one to choose from.
*/
private static class DisplayName extends Object {
private IIndexName name;
private IIndexBinding binding;
public DisplayName(IIndexName name, IIndexBinding binding) {
this.name = name;
this.binding= binding;
}
@Override
public String toString() {
try {
if (binding != null) {
return getBindingQualifiedName(binding) + " - " + name.getFileLocation().getFileName(); //$NON-NLS-1$
}
return null;
} catch (CoreException e) {
CUIPlugin.log(e);
return null;
}
}
public IIndexName getName() {
return name;
}
public IIndexBinding getBinding() {
return binding;
}
}
/**
* Extract the includes for the given selection. This can be both used to perform
* the work as well as being invoked when there is a change. The actual results
* can and should be cached as the lookup process could be potentially costly.
* the work as well as being invoked when there is a change.
* @param index
*/
private void extractIncludes(ITextEditor editor, IIndex index) {
if (editor == null) {
private void deduceInclude(ITextSelection selection, IASTTranslationUnit ast, String[] lookupName)
throws CoreException {
IASTNodeSelector selector = ast.getNodeSelector(fTu.getLocation().toOSString());
IASTName name = selector.findEnclosingName(selection.getOffset(), selection.getLength());
if (name == null) {
return;
}
char[] nameChars = name.toCharArray();
IBinding binding = name.resolveBinding();
try {
if (binding instanceof ICPPVariable) {
IType type = ((ICPPVariable) binding).getType();
type = SemanticUtil.getNestedType(type,
SemanticUtil.CVQ | SemanticUtil.PTR | SemanticUtil.ARRAY | SemanticUtil.REF);
if (type instanceof IBinding) {
binding = (IBinding) type;
nameChars = binding.getNameCharArray();
}
}
} catch (DOMException e) {
CUIPlugin.log(e);
}
if (nameChars.length == 0) {
return;
}
IIndex index = ast.getIndex();
final IndexFilter filter = IndexFilter.getDeclaredBindingFilter(ast.getLinkage().getLinkageID(), false);
IIndexBinding[] bindings= index.findBindings(nameChars, false, filter, new NullProgressMonitor());
final Map<String, IncludeCandidate> candidatesMap= new HashMap<String, IncludeCandidate>();
for (IIndexBinding indexBinding : bindings) {
IIndexName[] definitions= null;
// class, struct, union, enum
if (indexBinding instanceof ICompositeType || indexBinding instanceof IEnumeration) {
definitions= index.findDefinitions(indexBinding);
} else if (indexBinding instanceof ITypedef ||
(indexBinding instanceof IFunction && !(indexBinding instanceof ICPPMethod))) {
definitions= index.findDeclarations(indexBinding);
}
if (definitions != null) {
for (IIndexName definition : definitions) {
considerForInclusion(definition, indexBinding, index, candidatesMap);
}
}
}
IIndexMacro[] macros = index.findMacros(nameChars, filter, new NullProgressMonitor());
for (IIndexMacro macro : macros) {
IIndexName definition = macro.getDefinition();
considerForInclusion(definition, macro, index, candidatesMap);
}
ISelection s= editor.getSelectionProvider().getSelection();
IDocument doc= editor.getDocumentProvider().getDocument(editor.getEditorInput());
if (s.isEmpty() || !(s instanceof ITextSelection) || doc == null) {
return;
}
ITextSelection selection= (ITextSelection) s;
try {
IRegion region = CWordFinder.findWord(doc, selection.getOffset());
if (region == null || region.getLength() == 0) {
return;
}
String name = doc.get(region.getOffset(), region.getLength());
if (name.length() == 0) {
return;
}
// Try contribution from plugins.
IFunctionSummary fs = findContribution(name);
if (fs != null) {
fRequiredIncludes = fs.getIncludes();
String ns = fs.getNamespace();
if (ns != null && ns.length() > 0) {
fUsings = new String[] { fs.getNamespace() };
}
}
try {
IndexFilter filter= IndexFilter.ALL_DECLARED_OR_IMPLICIT;
IIndexBinding[] bindings= index.findBindings(name.toCharArray(), false, filter,
new NullProgressMonitor());
ArrayList<DisplayName> pdomNames= new ArrayList<DisplayName>();
for (int i = 0; i < bindings.length; ++i) {
IIndexBinding binding= bindings[i];
IIndexName[] defs= null;
// class, struct union, enumeration
if (binding instanceof ICompositeType || binding instanceof IEnumeration) {
defs= index.findDefinitions(binding);
} else if (binding instanceof ITypedef || binding instanceof IFunction) {
defs= index.findDeclarations(binding);
}
if (defs != null) {
for (IIndexName def : defs) {
pdomNames.add(new DisplayName(def, binding));
}
}
}
if (pdomNames.size() > 1) {
ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_NAME_ONLY));
dialog.setElements(pdomNames.toArray());
final ArrayList<IncludeCandidate> candidates = new ArrayList<IncludeCandidate>(candidatesMap.values());
if (candidates.size() > 1) {
runInUIThread(new Runnable() {
public void run() {
ElementListSelectionDialog dialog=
new ElementListSelectionDialog(getShell(), new LabelProvider());
dialog.setElements(candidates.toArray());
dialog.setTitle(CEditorMessages.AddIncludeOnSelection_label);
dialog.setMessage(CEditorMessages.AddIncludeOnSelection_description);
if (dialog.open() == Window.OK) {
//get selection
Object[] selects = dialog.getResult();
fRequiredIncludes = new IRequiredInclude[selects.length];
List<String> usings = new ArrayList<String>(selects.length);
for (int i = 0; i < fRequiredIncludes.length; i++) {
IRequiredInclude include = getRequiredInclude(
((DisplayName)selects[i]).getName().getFileLocation().getFileName(), getTranslationUnit());
if (include != null) {
fRequiredIncludes[i] = include;
IIndexBinding binding = ((DisplayName)selects[i]).getBinding();
if (binding instanceof ICPPBinding)
{
//find the enclosing namespace, if there's one
IQualifiedTypeName qualifiedName = new QualifiedTypeName(getBindingQualifiedName(binding));
String qualifiedEnclosingName = (new QualifiedTypeName(qualifiedName.getEnclosingNames())).getFullyQualifiedName();
if (!qualifiedEnclosingName.equals("")) //$NON-NLS-1$
usings.add(qualifiedEnclosingName);
}
}
}
if (usings.size() > 0)
{
fUsings = new String[usings.size()];
for (int i = 0; i < usings.size(); i++)
{
fUsings[i] = usings.get(i);
}
}
}
} else if (pdomNames.size() == 1) {
// we should use the IIndexName.getLocation here rather than getFileLocation
String fileName = (pdomNames.get(0)).getName().getFileLocation().getFileName();
fRequiredIncludes = new IRequiredInclude[] {getRequiredInclude(fileName, getTranslationUnit())};
IIndexBinding binding = (pdomNames.get(0)).getBinding();
if (binding instanceof ICPPBinding) {
//find the enclosing namespace, if there's one
IQualifiedTypeName qualifiedName = new QualifiedTypeName(getBindingQualifiedName(binding));
String qualifiedEnclosingName = new QualifiedTypeName(qualifiedName.getEnclosingNames()).getFullyQualifiedName();
if (!qualifiedEnclosingName.equals("")) //$NON-NLS-1$
fUsings = new String[] {qualifiedEnclosingName};
candidates.clear();
candidates.add((IncludeCandidate) dialog.getFirstResult());
}
}
} catch (CoreException e) {
e.printStackTrace();
}
// Try the type caching.
if (fRequiredIncludes == null && fUsings == null) {
}
});
}
// Do a full search
if (fRequiredIncludes == null && fUsings == null) {
fRequiredIncludes = null;
fUsingDeclarations = null;
if (candidates.size() == 1) {
IncludeCandidate candidate = candidates.get(0);
fRequiredIncludes = new IRequiredInclude[] { candidate.getInclude() };
IIndexBinding indexBinding = candidate.getBinding();
if (indexBinding instanceof ICPPBinding && !(indexBinding instanceof IIndexMacro)) {
// Decide what 'using' declaration should be added along with the include.
if (binding == null) {
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
}
String usingDeclaration = deduceUsingDeclaration(binding, indexBinding);
if (usingDeclaration != null)
fUsingDeclarations = new String[] { usingDeclaration };
}
} catch (BadLocationException e) {
MessageDialog.openError(getShell(), CEditorMessages.AddIncludeOnSelection_error_message3,
CEditorMessages.AddIncludeOnSelection_error_message4 + e.getMessage());
}
}
private IFunctionSummary findContribution (final String name) {
/**
* Adds an include candidate to the <code>candidates</code> map if the file containing
* the definition is suitable for inclusion.
*/
private void considerForInclusion(IIndexName definition, IIndexBinding binding,
IIndex index, Map<String, IncludeCandidate> candidates) throws CoreException {
IIndexFile file = definition.getFile();
// Consider the file for inclusion only if it is not a source file,
// 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);
IncludeCandidate candidate = new IncludeCandidate(binding, include);
if (!candidates.containsKey(candidate.toString())) {
candidates.put(candidate.toString(), candidate);
}
}
}
private String deduceUsingDeclaration(IBinding source, IBinding target) {
if (source.equals(target)) {
return null; // No using declaration is needed.
}
ArrayList<String> targetChain = getUsingChain(target);
if (targetChain.size() <= 1) {
return null; // Target is not in a namespace
}
ArrayList<String> sourceChain = getUsingChain(source);
if (sourceChain.size() >= targetChain.size()) {
int j = targetChain.size();
for (int i = sourceChain.size(); --j >= 1 && --i >= 1;) {
if (!sourceChain.get(i).equals(targetChain.get(j))) {
break;
}
}
if (j <= 0) {
return null; // Source is in the target's namespace
}
}
StringBuilder buf = new StringBuilder();
for (int i = targetChain.size(); --i >= 0;) {
if (buf.length() > 0) {
buf.append("::"); //$NON-NLS-1$
}
buf.append(targetChain.get(i));
}
return buf.toString();
}
private ArrayList<String> getUsingChain(IBinding binding) {
ArrayList<String> chain = new ArrayList<String>(4);
try {
for (; binding != null; binding = binding.getOwner()) {
String name = binding.getName();
if (binding instanceof ICPPNamespace) {
if (name.length() == 0) {
continue;
}
} else {
chain.clear();
}
chain.add(name);
}
} catch (DOMException e) {
CUIPlugin.log(e);
}
return chain;
}
/**
* Given a header file, decides if this header file should be included directly or
* through another header file. For example, <code>bits/stl_map.h</code> is not supposed
* to be included directly, but should be represented by <code>map</code>.
* @return the header file to include.
*/
private IIndexFile getRepresentativeFile(IIndexFile headerFile, IIndex index) {
try {
if (ResourceLookup.findFilesForLocationURI(headerFile.getLocation().getURI()).length > 0) {
return headerFile;
}
// TODO(sprigogin): Change to ArrayDeque when Java 5 support is no longer needed.
LinkedList<IIndexFile> front = new LinkedList<IIndexFile>();
front.add(headerFile);
HashSet<IIndexFile> processed = new HashSet<IIndexFile>();
processed.add(headerFile);
while (!front.isEmpty()) {
IIndexFile file = front.remove();
// A header without an extension is a good candidate for inclusion into a C++ source file.
if (fTu.isCXXLanguage() && !hasExtension(getPath(file))) {
return file;
}
IIndexInclude[] includes = index.findIncludedBy(file, 0);
for (IIndexInclude include : includes) {
IIndexFile includer = include.getIncludedBy();
if (!processed.contains(includer)) {
URI uri = includer.getLocation().getURI();
if (isSource(uri.getPath()) || ResourceLookup.findFilesForLocationURI(uri).length > 0) {
return file;
}
front.add(includer);
processed.add(includer);
}
}
}
} catch (CoreException e) {
CUIPlugin.log(e);
}
return headerFile;
}
private boolean hasExtension(String path) {
return path.indexOf('.', path.lastIndexOf('/') + 1) >= 0;
}
private IFunctionSummary findContribution(final String name) {
final IFunctionSummary[] fs = new IFunctionSummary[1];
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
ICHelpInvocationContext context = new ICHelpInvocationContext() {
public IProject getProject() {
ITranslationUnit u = getTranslationUnit();
if (u != null) {
return u.getCProject().getProject();
}
return null;
return fProject;
}
public ITranslationUnit getTranslationUnit() {
return AddIncludeOnSelectionAction.this.getTranslationUnit();
return fTu;
}
};
@ -353,91 +418,204 @@ public class AddIncludeOnSelectionAction extends Action implements IUpdate {
try {
PlatformUI.getWorkbench().getProgressService().busyCursorWhile(op);
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getShell(), CEditorMessages.AddIncludeOnSelection_error_message1, null);
ExceptionHandler.handle(e, getShell(), CEditorMessages.AddIncludeOnSelection_error_title,
CEditorMessages.AddIncludeOnSelection_help_provider_error);
} catch (InterruptedException e) {
// Do nothing. Operation has been canceled.
}
return fs[0];
}
public void setContentEditor(ITextEditor editor) {
fEditor= editor;
private void runInUIThread(Runnable runnable) {
if (Display.getCurrent() != null) {
runnable.run();
} else {
Display.getDefault().syncExec(runnable);
}
}
@Override
public void update() {
setEnabled(getTranslationUnit() != null);
ITextEditor editor = getTextEditor();
setEnabled(editor != null && getTranslationUnit(editor) != null);
}
/**
* Checks if a file is a source file (.c, .cpp, .cc, etc). Header files are not considered source files.
* @return Returns <code>true</code> if the the file is a source file.
*/
private boolean isSource(String filename) {
IContentType ct= CCorePlugin.getContentType(fProject, filename);
if (ct != null) {
String id = ct.getId();
if (CCorePlugin.CONTENT_TYPE_CSOURCE.equals(id) || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(id)) {
return true;
}
}
return false;
}
private static String getPath(IIndexFile file) throws CoreException {
return file.getLocation().getURI().getPath();
}
/**
* Returns the RequiredInclude object to be added to the include list
* @param path - the full path of the file to include
* @param tu - the translation unit which requires the include
* @return the required include
* @throws CoreException
*/
private IRequiredInclude getRequiredInclude(String path, ITranslationUnit tu) {
if (path != null) {
IPath typeLocation = new Path(path);
IProject project = tu.getCProject().getProject();
IPath projectLocation = project.getLocation();
IPath workspaceLocation = project.getWorkspace().getRoot().getLocation();
IPath headerLocation = tu.getResource().getLocation();
boolean isSystemIncludePath = false;
private IRequiredInclude getRequiredInclude(IIndexFile file, IIndex index) throws CoreException {
IIndexInclude[] includes;
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.
int systemIncludeVotes = 0;
String[] ballotBox = new String[includes.length];
for (int i = 0; i < includes.length; i++) {
IIndexInclude include = includes[i];
if (isResolvable(include)) {
ballotBox[i] = include.getFullName();
if (include.isSystemInclude()) {
systemIncludeVotes++;
}
}
}
Arrays.sort(ballotBox);
String contender = ballotBox[0];
int votes = 1;
String winner = contender;
int winnerVotes = votes;
for (int i = 1; i < ballotBox.length; i++) {
if (!ballotBox[i].equals(contender)) {
contender = ballotBox[i];
votes = 1;
}
votes++;
if (votes > winnerVotes) {
winner = contender;
winnerVotes = votes;
}
}
return new RequiredInclude(winner, systemIncludeVotes * 2 >= includes.length);
}
IPath includePath = makeRelativePathToProjectIncludes(typeLocation, tu);
if (includePath != null && !projectLocation.isPrefixOf(typeLocation)) {
isSystemIncludePath = true;
}
//create a relative path - the include file is in the same project as the file we're currently at
else if (projectLocation.isPrefixOf(typeLocation)
&& projectLocation.isPrefixOf(headerLocation)) {
includePath = PathUtil.makeRelativePath(typeLocation, headerLocation.removeLastSegments(1));
}
//create a relative path - the include file is in the same workspace as the file we're currently at
else if (workspaceLocation.isPrefixOf(typeLocation))
{
includePath = PathUtil.makeRelativePath(typeLocation, projectLocation);
}
if (includePath == null)
includePath = typeLocation; //the full path
return new RequiredIncludes(includePath.toString(), isSystemIncludePath);
// The file has never been included before.
IPath targetLocation = PathUtil.getCanonicalPath(new Path(file.getLocation().getURI().getPath()));
IPath sourceLocation = PathUtil.getCanonicalPath(fTu.getResource().getLocation());
boolean isSystemIncludePath = false;
IPath path = PathUtil.makeRelativePathToIncludes(targetLocation, fIncludePath);
if (path != null &&
ResourceLookup.findFilesForLocationURI(URI.create(targetLocation.toString())).length == 0) {
// A header file in the include path but outside the workspace is included with angle brackets.
isSystemIncludePath = true;
}
return null;
if (path == null) {
IPath sourceDirectory = sourceLocation.removeLastSegments(1);
if (PathUtil.isPrefix(sourceDirectory, targetLocation)) {
path = targetLocation.removeFirstSegments(sourceDirectory.segmentCount());
} else {
path = targetLocation;
}
}
return new RequiredInclude(path.toString(), isSystemIncludePath);
}
/**
* Create a relative path to the project includes.
* @param fullPath the full path to the project
* @param tu a translation unit in the project
* @return IPath corresponding to a relative path to the project includes
* Returns <code>true</code> if the given include can be resolved in the context of
* the current translation unit.
*/
private static IPath makeRelativePathToProjectIncludes(IPath fullPath, ITranslationUnit tu) {
IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(tu.getCProject().getProject());
if (provider != null) {
IScannerInfo info = provider.getScannerInformation(tu.getResource());
if (info != null) {
return PathUtil.makeRelativePathToIncludes(fullPath, info.getIncludePaths());
}
}
return null;
}
private boolean isResolvable(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;
}
return target.equals(new File(new File(fTu.getLocationURI().getPath()).getParent(), includeName));
} catch (CoreException e) {
CUIPlugin.log(e);
return false;
}
}
/**
* Get the fully qualified name for a given PDOMBinding
* @param pdomBinding
* Get the fully qualified name for a given index binding.
* @param binding
* @return binding's fully qualified name
* @throws CoreException
*/
private static String getBindingQualifiedName(IIndexBinding binding) throws CoreException {
StringBuffer buf = new StringBuffer();
String[] qname= binding.getQualifiedName();
for (int i = 0; i < qname.length; i++) {
if (i > 0) {
buf.append("::"); //$NON-NLS-1$
}
buf.append(qname[i]);
return CPPVisitor.renderQualifiedName(qname);
}
/**
* To be used by ElementListSelectionDialog for user to choose which declarations/
* definitions for "add include" when there are more than one to choose from.
*/
private static class IncludeCandidate {
private final IIndexBinding binding;
private final IRequiredInclude include;
private final String label;
public IncludeCandidate(IIndexBinding binding, IRequiredInclude include) throws CoreException {
this.binding = binding;
this.include = include;
this.label = getBindingQualifiedName(binding) + " - " + include.toString(); //$NON-NLS-1$
}
public IIndexBinding getBinding() {
return binding;
}
public IRequiredInclude getInclude() {
return include;
}
@Override
public String toString() {
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()
*/
public String getIncludeName() {
return includeName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.ui.IRequiredInclude#isStandard()
*/
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();
}
return buf.toString();
}
}

View file

@ -10,22 +10,36 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.ResourceBundle;
import org.eclipse.osgi.util.NLS;
public final class CEditorMessages extends NLS {
private static final String BUNDLE_FOR_CONSTRUCTED_KEYS=
"org.eclipse.cdt.internal.ui.editor.ConstructedCEditorMessages"; //$NON-NLS-1$
private static ResourceBundle fgBundleForConstructedKeys= ResourceBundle.getBundle(BUNDLE_FOR_CONSTRUCTED_KEYS);
private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.editor.CEditorMessages";//$NON-NLS-1$
/**
* Returns the message bundle which contains constructed keys.
*
* @return the message bundle
* @since 5.1
*/
public static ResourceBundle getBundleForConstructedKeys() {
return fgBundleForConstructedKeys;
}
private static final String BUNDLE_NAME = CEditorMessages.class.getName();
private CEditorMessages() {
// Do not instantiate
}
public static String AddIncludeOnSelection_description;
public static String AddIncludeOnSelection_error_message1;
public static String AddIncludeOnSelection_error_message3;
public static String AddIncludeOnSelection_error_message4;
public static String AddIncludeOnSelection_label;
public static String AddIncludeOnSelection_tooltip;
public static String AddIncludeOnSelection_description;
public static String AddIncludeOnSelection_error_title;
public static String AddIncludeOnSelection_insertion_failed;
public static String AddIncludeOnSelection_help_provider_error;
public static String AddIncludesOperation_description;
public static String ShowInCView_description;
public static String ShowInCView_label;

View file

@ -10,14 +10,14 @@
# QNX Software System
# Anton Leherbauer (Wind River Systems)
# Markus Schorn (Wind River Systems)
# Sergey Prigogin (Google)
#########################################
AddIncludeOnSelection_description=Add include statement on selection
AddIncludeOnSelection_error_message1=Adding include statements failed
AddIncludeOnSelection_error_message3=Error
AddIncludeOnSelection_error_message4=BadLocationException:
AddIncludeOnSelection_label=Add Include
AddIncludeOnSelection_tooltip=Add Include Statement on Selection
AddIncludeOnSelection_description=Add include statement for selected name
AddIncludeOnSelection_error_title=Error Adding Include
AddIncludeOnSelection_insertion_failed=Adding include statements failed
AddIncludeOnSelection_help_provider_error=Help provider error
AddIncludesOperation_description=Adding include statement
ShowInCView_description=Show the current resource in the C/C++ Projects view

View file

@ -10,11 +10,12 @@
# QNX Software System
# Anton Leherbauer (Wind River Systems)
# Markus Schorn (Wind River Systems)
# Sergey Prigogin (Google)
#########################################
AddIncludeOnSelection.description=Add include statement on selection
AddIncludeOnSelection.description=Add include statement for selected name
AddIncludeOnSelection.label=Add Include
AddIncludeOnSelection.tooltip=Add Include Statement on Selection
AddIncludeOnSelection.tooltip=Add Include Statement for Selected Name
OpenOutline.label= Quick Out&line
OpenOutline.tooltip= Shows the Quick Outline of Editor Input