From e157e1a63e2b1c81ceeec7e6efaa953ce90b5c22 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Thu, 29 Mar 2012 13:54:50 -0400 Subject: [PATCH] More cleanup --- .../providers/BuiltinSpecsDetectorTest.java | 12 +- .../providers/GCCBuildCommandParserTest.java | 8 +- .../providers/AbstractBuildCommandParser.java | 48 +++- .../AbstractBuiltinSpecsDetector.java | 5 +- ...AbstractLanguageSettingsOutputScanner.java | 269 ++++++++++-------- .../providers/GCCBuiltinSpecsDetector.java | 2 +- .../providers/IWorkingDirectoryTracker.java | 28 +- .../eclipse/cdt/core/ErrorParserManager.java | 1 + .../xlc/core/XlcBuiltinSpecsDetector.java | 2 +- 9 files changed, 218 insertions(+), 157 deletions(-) diff --git a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/BuiltinSpecsDetectorTest.java b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/BuiltinSpecsDetectorTest.java index c9726e38ddb..251aae6b49a 100644 --- a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/BuiltinSpecsDetectorTest.java +++ b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/BuiltinSpecsDetectorTest.java @@ -58,7 +58,7 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase { private class MockBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector { @Override - protected List parseForOptions(String line) { + protected List parseOptions(String line) { return null; } @Override @@ -82,7 +82,7 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase { private class MockBuiltinSpecsDetectorExecutedFlag extends AbstractBuiltinSpecsDetector { @Override - protected List parseForOptions(String line) { + protected List parseOptions(String line) { return null; } @Override @@ -120,7 +120,7 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase { return super.runForEachLanguage(monitor); } @Override - protected List parseForOptions(final String line) { + protected List parseOptions(final String line) { return new ArrayList() {{ add(line); }}; } @Override @@ -140,7 +140,11 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase { @Override protected void tearDown() throws Exception { - Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null); + try { + Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null); + } catch (Exception e) { + // ignore + } super.tearDown(); } diff --git a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/GCCBuildCommandParserTest.java b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/GCCBuildCommandParserTest.java index 45c8f1f9434..64ce467b106 100644 --- a/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/GCCBuildCommandParserTest.java +++ b/build/org.eclipse.cdt.make.core.tests/src/org/eclipse/cdt/make/language/settings/providers/GCCBuildCommandParserTest.java @@ -92,7 +92,11 @@ public class GCCBuildCommandParserTest extends BaseTestCase { @Override protected void tearDown() throws Exception { - Job.getJobManager().join(AbstractBuildCommandParser.JOB_FAMILY_BUILD_COMMAND_PARSER, null); + try { + Job.getJobManager().join(AbstractBuildCommandParser.JOB_FAMILY_BUILD_COMMAND_PARSER, null); + } catch (Exception e) { + // ignore + } super.tearDown(); } @@ -1745,7 +1749,7 @@ public class GCCBuildCommandParserTest extends BaseTestCase { public void testContentType_None() throws Exception { MockBuildCommandParser parser = new MockBuildCommandParser() { @Override - protected String parseForResourceName(String line) { + protected String parseResourceName(String line) { return "file.wrong-content-type"; } }; diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuildCommandParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuildCommandParser.java index d99cbab9069..6bff1fa1f2b 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuildCommandParser.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuildCommandParser.java @@ -12,10 +12,14 @@ package org.eclipse.cdt.make.core.language.settings.providers; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.IErrorParser2; import org.eclipse.cdt.core.IMarkerGenerator; import org.eclipse.cdt.core.errorparsers.RegexErrorParser; @@ -28,6 +32,9 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; @@ -96,9 +103,42 @@ public abstract class AbstractBuildCommandParser extends AbstractLanguageSetting return pattern; } + @SuppressWarnings("nls") + private static String expressionLogicalOr(Set fileExts) { + String pattern = "("; + for (String ext : fileExts) { + if (pattern.length() != 1) + pattern += "|"; + pattern += "(" + Pattern.quote(ext) + ")"; + ext = ext.toUpperCase(); + if (!fileExts.contains(ext)) { + pattern += "|(" + Pattern.quote(ext) + ")"; + } + } + pattern += ")"; + return pattern; + } + + protected String getPatternFileExtensions() { + IContentTypeManager manager = Platform.getContentTypeManager(); + + Set fileExts = new HashSet(); + + IContentType contentTypeCpp = manager.getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE); + fileExts.addAll(Arrays.asList(contentTypeCpp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC))); + + IContentType contentTypeC = manager.getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE); + fileExts.addAll(Arrays.asList(contentTypeC.getFileSpecs(IContentType.FILE_EXTENSION_SPEC))); + + String pattern = expressionLogicalOr(fileExts); + + return pattern; + } + + @Override - protected String parseForResourceName(String line) { - if (line==null) { + protected String parseResourceName(String line) { + if (line == null) { return null; } @@ -115,8 +155,8 @@ public abstract class AbstractBuildCommandParser extends AbstractLanguageSetting } @Override - protected List parseForOptions(String line) { - if (line==null || currentResource==null) { + protected List parseOptions(String line) { + if (line == null || currentResource == null) { return null; } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuiltinSpecsDetector.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuiltinSpecsDetector.java index 8e72c623a23..42ffb3193ec 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuiltinSpecsDetector.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractBuiltinSpecsDetector.java @@ -264,7 +264,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti * TODO */ @Override - protected String parseForResourceName(String line) { + protected String parseResourceName(String line) { // Returning null works as if workspace-wide return null; } @@ -319,10 +319,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti mappedRootURI = null; buildDirURI = null; - ICConfigurationDescription cfgDescription = currentCfgDescription; super.shutdown(); - // keep currentCfgDescription, do not let super.shutdown() to clear it - currentCfgDescription = cfgDescription; } protected void execute() { diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractLanguageSettingsOutputScanner.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractLanguageSettingsOutputScanner.java index 6446a6ddea7..9765042bc8a 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractLanguageSettingsOutputScanner.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/language/settings/providers/AbstractLanguageSettingsOutputScanner.java @@ -16,8 +16,6 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -26,6 +24,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; import org.eclipse.cdt.core.language.settings.providers.ICBuildOutputParser; @@ -50,9 +49,6 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.content.IContentTypeManager; import org.w3c.dom.Element; /** @@ -61,7 +57,6 @@ import org.w3c.dom.Element; * @since 7.2 */ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSettingsSerializableProvider implements ICBuildOutputParser { - protected static final String ATTR_KEEP_RELATIVE_PATHS = "keep-relative-paths"; //$NON-NLS-1$ protected ICConfigurationDescription currentCfgDescription = null; @@ -197,18 +192,18 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett * or "applicable to any resource". By default "no resource found" is used in this * abstract class but extenders can handle otherwise. */ - protected abstract String parseForResourceName(String line); + protected abstract String parseResourceName(String line); /** * Parse the line returning the list of substrings to be treated each as input to * the option parsers. It is assumed that each substring presents one * {@link ICLanguageSettingEntry} (for example compiler options {@code -I/path} or - * {@code -DMACRO=1}. + * {@code -DMACRO=1}). * * @param line - one input line from the output stripped from end of line characters. * @return list of substrings representing language settings entries. */ - protected abstract List parseForOptions(String line); + protected abstract List parseOptions(String line); /** * @return array of option parsers defining how to parse a string to @@ -228,36 +223,35 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett @Override public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException { - this.cwdTracker = cwdTracker; this.currentCfgDescription = cfgDescription; this.currentProject = cfgDescription != null ? cfgDescription.getProjectDescription().getProject() : null; + this.cwdTracker = cwdTracker; } @Override public void shutdown() { // release resources for garbage collector - currentCfgDescription = null; - currentProject = null; - currentResource = null; - currentLanguageId = null; - - cwdTracker = null; + // but keep currentCfgDescription for AbstractBuiltinSpecsDetector flow parsedResourceName = null; + currentLanguageId = null; + currentResource = null; + cwdTracker = null; } @Override public boolean processLine(String line) { - parsedResourceName = parseForResourceName(line); + parsedResourceName = parseResourceName(line); currentResource = findResource(parsedResourceName); currentLanguageId = determineLanguage(); - if (!isLanguageInScope(currentLanguageId)) + if (!isLanguageInScope(currentLanguageId)) { return false; + } /** - * URI of directory where the build is happening. This URI could point to a remote filesystem - * for remote builds. Most often it is the same filesystem as for currentResource but - * it can be different filesystem (and different URI schema). + * URI of directory where the build is happening. This URI could point to a remote file-system + * for remote builds. Most often it is the same file-system as for currentResource but + * it can be different file-system (and different URI schema). */ URI buildDirURI = null; @@ -265,7 +259,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett * Where source tree starts if mapped. This kind of mapping is useful for example in cases when * the absolute path to the source file on the remote system is simulated inside a project in the * workspace. - * This URI is rooted on the same filesystem where currentResource resides. In general this filesystem + * This URI is rooted on the same file-system where currentResource resides. In general this file-system * (or even URI schema) does not have to match that of buildDirURI. */ URI mappedRootURI = null; @@ -277,17 +271,18 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett List entries = new ArrayList(); - List options = parseForOptions(line); - if (options!=null) { + List options = parseOptions(line); + if (options != null) { for (String option : options) { - @SuppressWarnings("unused") - int i =0; for (AbstractOptionParser optionParser : getOptionParsers()) { try { if (optionParser.parseOption(option)) { ICLanguageSettingEntry entry = null; if (isResolvingPaths && optionParser.isPathKind()) { - URI baseURI = new Path(optionParser.parsedName).isAbsolute() ? mappedRootURI : buildDirURI; + URI baseURI = mappedRootURI; + if (!new Path(optionParser.parsedName).isAbsolute() && buildDirURI != null) { + baseURI = EFSExtensionManager.getDefault().append(mappedRootURI, buildDirURI.getPath()); + } entry = createResolvedPathEntry(optionParser, optionParser.parsedName, 0, baseURI); } else { entry = optionParser.createEntry(optionParser.parsedName, optionParser.parsedValue, 0); @@ -313,7 +308,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return false; } - // TODO - remove me + // TODO - temporary, remove me @Deprecated protected String getPrefixForLog() { String str; @@ -334,12 +329,17 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett + getClass().getSimpleName() + " collected " + (entries!=null ? ("" + entries.size()) : "null") + " entries for " + currentResource); } + /** + * Determine a language associated with the resource. + * + * @return language ID for the resource. + */ protected String determineLanguage() { IResource rc = currentResource; if (rc == null && currentProject != null && parsedResourceName != null) { String fileName = new Path(parsedResourceName).lastSegment().toString(); // use handle; resource does not need to exist - rc = currentProject.getFile("__" + fileName); + rc = currentProject.getFile("__" + fileName); //$NON-NLS-1$ } if (rc == null) @@ -352,31 +352,23 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return languageIds.get(0); } + /** + * Determine if the language is in scope of the provider. + * + * @param languageId - language ID. + * @return {@code true} if the language is in scope, {@code false } otherwise. + */ protected boolean isLanguageInScope(String languageId) { List languageIds = getLanguageScope(); return languageIds == null || languageIds.contains(languageId); } - protected String getPatternFileExtensions() { - IContentTypeManager manager = Platform.getContentTypeManager(); - - Set fileExts = new HashSet(); - - IContentType contentTypeCpp = manager.getContentType("org.eclipse.cdt.core.cxxSource"); - fileExts.addAll(Arrays.asList(contentTypeCpp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC))); - - IContentType contentTypeC = manager.getContentType("org.eclipse.cdt.core.cSource"); - fileExts.addAll(Arrays.asList(contentTypeC.getFileSpecs(IContentType.FILE_EXTENSION_SPEC))); - - String pattern = expressionLogicalOr(fileExts); - - return pattern; - } - + /** + * Resolve and create language settings path entry. + */ private ICLanguageSettingEntry createResolvedPathEntry(AbstractOptionParser optionParser, String parsedPath, int flag, URI baseURI) { - ICLanguageSettingEntry entry; String resolvedPath = null; URI uri = determineMappedURI(parsedPath, baseURI); @@ -415,25 +407,39 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett resolvedPath = parsedPath; } - entry = optionParser.createEntry(resolvedPath, resolvedPath, flag); - return entry; + return optionParser.createEntry(resolvedPath, resolvedPath, flag); } + /** + * Determine resource in the workspace corresponding to the parsed resource name. + */ private IResource findResource(String parsedResourceName) { - if (parsedResourceName == null) + if (parsedResourceName == null || parsedResourceName.isEmpty()) { return null; + } IResource sourceFile = null; // try ErrorParserManager - if (cwdTracker != null) { - sourceFile = cwdTracker.findFileName(parsedResourceName); + if (cwdTracker instanceof ErrorParserManager) { + sourceFile = ((ErrorParserManager) cwdTracker).findFileName(parsedResourceName); } + // try to find absolute path in the workspace if (sourceFile == null && new Path(parsedResourceName).isAbsolute()) { URI uri = org.eclipse.core.filesystem.URIUtil.toURI(parsedResourceName); sourceFile = findFileForLocationURI(uri, currentProject); } + + // try last known current working directory from build output + if (sourceFile == null && cwdTracker != null) { + URI cwdURI = cwdTracker.getWorkingDirectoryURI(); + if (cwdURI != null) { + URI uri = EFSExtensionManager.getDefault().append(cwdURI, parsedResourceName); + sourceFile = findFileForLocationURI(uri, currentProject); + } + } + // try path relative to build dir from configuration if (sourceFile == null && currentCfgDescription != null) { IPath builderCWD = currentCfgDescription.getBuildSetting().getBuilderCWD(); @@ -443,24 +449,30 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett sourceFile = findFileForLocationURI(uri, currentProject); } } + // try path relative to the project if (sourceFile == null && currentProject != null) { sourceFile = currentProject.findMember(parsedResourceName); } + return sourceFile; } + /** + * Determine current build directory considering currentResource (resource being compiled), + * parsedResourceName and mappedRootURI. + * + * @param mappedRootURI - root of the source tree when mapped to remote file-system. + * @return {@link URI} of current build directory + */ protected URI getBuildDirURI(URI mappedRootURI) { URI buildDirURI = null; + // try to deduce build directory from full path of currentResource and partial path of parsedResourceName URI cwdURI = null; - if (currentResource!=null && parsedResourceName!=null && !new Path(parsedResourceName).isAbsolute()) { + if (currentResource != null && parsedResourceName != null && !new Path(parsedResourceName).isAbsolute()) { cwdURI = findBaseLocationURI(currentResource.getLocationURI(), parsedResourceName); } - if (cwdURI == null && cwdTracker != null) { - cwdURI = cwdTracker.getWorkingDirectoryURI(); - } - String cwdPath = cwdURI != null ? EFSExtensionManager.getDefault().getPathFromURI(cwdURI) : null; if (cwdPath != null && mappedRootURI != null) { buildDirURI = EFSExtensionManager.getDefault().append(mappedRootURI, cwdPath); @@ -468,14 +480,21 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett buildDirURI = cwdURI; } + // if not found - try IWorkingDirectoryTracker + if (buildDirURI == null && cwdTracker != null) { + buildDirURI = cwdTracker.getWorkingDirectoryURI(); + } + + // if not found - try builder working directory if (buildDirURI == null && currentCfgDescription != null) { IPath pathBuilderCWD = currentCfgDescription.getBuildSetting().getBuilderCWD(); if (pathBuilderCWD != null) { String builderCWD = pathBuilderCWD.toString(); try { - // TODO - here is a hack to overcome ${workspace_loc:/prj-name} returned by builder + // here is a hack to overcome ${workspace_loc:/prj-name} returned by builder + // where "/" is treated as path separator by pathBuilderCWD ICdtVariableManager vmanager = CCorePlugin.getDefault().getCdtVariableManager(); - builderCWD = vmanager.resolveValue(builderCWD, "", null, currentCfgDescription); + builderCWD = vmanager.resolveValue(builderCWD, "", null, currentCfgDescription); //$NON-NLS-1$ } catch (CdtVariableException e) { MakeCorePlugin.log(e); } @@ -483,10 +502,12 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } } + // if not found - try directory of the current project if (buildDirURI == null && currentProject != null) { buildDirURI = currentProject.getLocationURI(); } + // if not found - try parent folder of the resource if (buildDirURI == null && currentResource != null) { IContainer container; if (currentResource instanceof IContainer) { @@ -500,7 +521,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } /** - * Determine URI on the local filesystem considering possible mapping. + * Determine URI on the local file-system considering possible mapping. * * @param pathStr - path to the resource, can be absolute or relative * @param baseURI - base {@link URI} where path to the resource is rooted @@ -509,22 +530,22 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett private static URI determineMappedURI(String pathStr, URI baseURI) { URI uri = null; - if (baseURI==null) { + if (baseURI == null) { if (new Path(pathStr).isAbsolute()) { uri = resolvePathFromBaseLocation(pathStr, Path.ROOT); } } else if (baseURI.getScheme().equals(EFS.SCHEME_FILE)) { - // location on the local filesystem + // location on the local file-system IPath baseLocation = org.eclipse.core.filesystem.URIUtil.toPath(baseURI); // careful not to use Path here but 'pathStr' as String as we want to properly navigate symlinks uri = resolvePathFromBaseLocation(pathStr, baseLocation); } else { - // location on a remote filesystem + // location on a remote file-system IPath path = new Path(pathStr); // use canonicalized path here, in particular replace all '\' with '/' for Windows paths URI remoteUri = EFSExtensionManager.getDefault().append(baseURI, path.toString()); - if (remoteUri!=null) { + if (remoteUri != null) { String localPath = EFSExtensionManager.getDefault().getMappedPath(remoteUri); - if (localPath!=null) { + if (localPath != null) { uri = org.eclipse.core.filesystem.URIUtil.toURI(localPath); } } @@ -537,6 +558,9 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return uri; } + /** + * Determine which resource in workspace is the best fit to parsedName passed. + */ private static IResource resolveResourceInWorkspace(String parsedName, IProject preferredProject, Set referencedProjectsNames) { IPath path = new Path(parsedName); if (path.equals(new Path(".")) || path.equals(new Path(".."))) { //$NON-NLS-1$ //$NON-NLS-2$ @@ -544,12 +568,12 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } // prefer current project - if (preferredProject!=null) { + if (preferredProject != null) { List result = findPathInFolder(path, preferredProject); int size = result.size(); - if (size==1) { // found the one + if (size == 1) { // found the one return result.get(0); - } else if (size>1) { // ambiguous + } else if (size > 1) { // ambiguous return null; } } @@ -564,7 +588,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett if (prj.isOpen()) { List result = findPathInFolder(path, prj); int size = result.size(); - if (size==1 && rc==null) { + if (size == 1 && rc == null) { rc = result.get(0); } else if (size > 0) { // ambiguous @@ -586,7 +610,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett if (!prj.equals(preferredProject) && !referencedProjectsNames.contains(prj.getName()) && prj.isOpen()) { List result = findPathInFolder(path, prj); int size = result.size(); - if (size==1 && rc==null) { + if (size == 1 && rc == null) { rc = result.get(0); } else if (size > 0) { // ambiguous @@ -595,7 +619,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } } } - if (rc!=null) { + if (rc != null) { return rc; } } @@ -604,6 +628,9 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return null; } + /** + * Find all resources in the folder which might be represented by relative path passed. + */ private static List findPathInFolder(IPath path, IContainer folder) { List paths = new ArrayList(); IResource resource = folder.findMember(path); @@ -624,26 +651,33 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return paths; } + /** + * Find resource in the workspace for a given URI with a preference for the resource + * to reside in the given project. + */ private static IResource findFileForLocationURI(URI uri, IProject preferredProject) { - IResource sourceFile; - IResource result = null; + IResource sourceFile = null; IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IResource[] resources = root.findFilesForLocationURI(uri); if (resources.length > 0) { - result = resources[0]; - if (preferredProject!=null) { + sourceFile = resources[0]; + if (preferredProject != null) { for (IResource rc : resources) { if (rc.getProject().equals(preferredProject)) { - result = rc; + sourceFile = rc; break; } } } } - sourceFile = result; return sourceFile; } + /** + * Find base location of the file, i.e. location of the directory which + * results from removing trailing relativeFileName from fileURI or + * {@code null} if fileURI doesn't represent relativeFileName. + */ private static URI findBaseLocationURI(URI fileURI, String relativeFileName) { URI cwdURI = null; String path = fileURI.getPath(); @@ -687,40 +721,44 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett * i.e URI where the root path would be mapped. The mapped root will be * used to prepend to other "absolute" paths where appropriate. * - * @param sourceFile - a resource referred by parsed path + * @param resource - a resource referred by parsed path * @param parsedResourceName - path as appears in the output * @return mapped path as URI */ - protected URI getMappedRootURI(IResource sourceFile, String parsedResourceName) { - if (currentResource==null) { + protected URI getMappedRootURI(IResource resource, String parsedResourceName) { + if (resource == null) { return null; } - URI fileURI = sourceFile.getLocationURI(); + URI resourceURI = resource.getLocationURI(); String mappedRoot = "/"; //$NON-NLS-1$ - if (parsedResourceName!=null) { + if (parsedResourceName != null) { IPath parsedSrcPath = new Path(parsedResourceName); if (parsedSrcPath.isAbsolute()) { - IPath absPath = sourceFile.getLocation(); - int absSegmentsCount = absPath.segmentCount(); + IPath absResourcePath = resource.getLocation(); + int absSegmentsCount = absResourcePath.segmentCount(); int relSegmentsCount = parsedSrcPath.segmentCount(); if (absSegmentsCount >= relSegmentsCount) { - IPath ending = absPath.removeFirstSegments(absSegmentsCount - relSegmentsCount); + IPath ending = absResourcePath.removeFirstSegments(absSegmentsCount - relSegmentsCount); ending = ending.setDevice(parsedSrcPath.getDevice()).makeAbsolute(); if (ending.equals(parsedSrcPath.makeAbsolute())) { - mappedRoot = absPath.removeLastSegments(relSegmentsCount).toString(); + // mappedRoot here is parsedSrcPath with removed parsedResourceName trailing segments, + // i.e. if absResourcePath="/path/workspace/project/file.c" and parsedResourceName="project/file.c" + // then mappedRoot="/path/workspace/" + mappedRoot = absResourcePath.removeLastSegments(relSegmentsCount).toString(); } } } } - URI uri = EFSExtensionManager.getDefault().createNewURIFromPath(fileURI, mappedRoot); + // this creates URI with schema and other components from resourceURI but path as mappedRoot + URI uri = EFSExtensionManager.getDefault().createNewURIFromPath(resourceURI, mappedRoot); return uri; } /** * The manipulations here are done to resolve "../" navigation for symbolic links where "link/.." cannot - * be collapsed as it must follow the real filesystem path. {@link java.io.File#getCanonicalPath()} deals + * be collapsed as it must follow the real file-system path. {@link java.io.File#getCanonicalPath()} deals * with that correctly but {@link Path} or {@link URI} try to normalize the path which would be incorrect * here. */ @@ -750,12 +788,15 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett // if error just leave it as is } - URI uri = org.eclipse.core.filesystem.URIUtil.toURI(pathName); - return uri; + return org.eclipse.core.filesystem.URIUtil.toURI(pathName); } + /** + * Return a resource in workspace corresponding the given {@link URI} preferable residing in + * the provided project. + */ private static IResource findResourceForLocationURI(URI uri, int kind, IProject preferredProject) { - if (uri==null) + if (uri == null) return null; IResource resource = null; @@ -774,32 +815,34 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return resource; } + /** + * Return a resource in workspace corresponding the given folder {@link URI} preferable residing in + * the provided project. + */ private static IResource findContainerForLocationURI(URI uri, IProject preferredProject) { IResource resource = null; - IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); - IResource[] resources = root.findContainersForLocationURI(uri); - if (resources.length > 0) { - for (IResource rc : resources) { - if ((rc instanceof IProject || rc instanceof IFolder)) { // treat IWorkspaceRoot as non-workspace path - IProject prj = rc instanceof IProject ? (IProject)rc : rc.getProject(); - if (prj.equals(preferredProject)) { - resource = rc; - break; - } - if (resource==null) { - resource=rc; // to be deterministic the first qualified resource has preference - } + IResource[] resources = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(uri); + for (IResource rc : resources) { + if ((rc instanceof IProject || rc instanceof IFolder)) { // treat IWorkspaceRoot as non-workspace path + if (rc.getProject().equals(preferredProject)) { + resource = rc; + break; + } + if (resource == null) { + resource = rc; // to be deterministic the first qualified resource has preference } } } return resource; } + /** + * Get location on the local file-system considering possible mapping by {@link EFSExtensionManager}. + */ private static IPath getFilesystemLocation(URI uri) { - if (uri==null) + if (uri == null) return null; - // EFSExtensionManager mapping String pathStr = EFSExtensionManager.getDefault().getMappedPath(uri); uri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr); @@ -813,22 +856,6 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return null; } - @SuppressWarnings("nls") - private static String expressionLogicalOr(Set fileExts) { - String pattern = "("; - for (String ext : fileExts) { - if (pattern.length() != 1) - pattern += "|"; - pattern += "(" + Pattern.quote(ext) + ")"; - ext = ext.toUpperCase(); - if (!fileExts.contains(ext)) { - pattern += "|(" + Pattern.quote(ext) + ")"; - } - } - pattern += ")"; - return pattern; - } - protected static int countGroups(String str) { @SuppressWarnings("nls") int count = str.replaceAll("[^\\(]", "").length(); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetector.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetector.java index 69250030db5..947f3b7df87 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetector.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetector.java @@ -57,7 +57,7 @@ public class GCCBuiltinSpecsDetector extends ToolchainBuiltinSpecsDetector imple } @Override - protected List parseForOptions(String line) { + protected List parseOptions(String line) { line = line.trim(); // contribution of -dD option diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/IWorkingDirectoryTracker.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/IWorkingDirectoryTracker.java index a0734c71a97..6bf62071aa3 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/IWorkingDirectoryTracker.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/IWorkingDirectoryTracker.java @@ -12,29 +12,17 @@ package org.eclipse.cdt.core.language.settings.providers; import java.net.URI; -import org.eclipse.core.resources.IFile; - /** - * TODO + * Interface for console parsers able to track current working directory for build. + * * @since 5.4 */ public interface IWorkingDirectoryTracker { - // TODO - define the API - - public URI getWorkingDirectoryURI(); - public IFile findFileName(String partialLoc); - - /* - public URI findFileURI(String partialLoc); - public URI findFolderURI(String partialLoc); - - or - public File findFile(String partialLoc); // best choice - public Folder findFolder(String partialLoc); // best choice - - or - public List findFileURI(String partialLoc); // all candidates - public List findFolderURI(String partialLoc); // all candidates - + /** + * Returns current working directory for the current build command as determined from + * build output. + * + * @return URI of current working directory or {@code null}. */ + public URI getWorkingDirectoryURI(); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java index d7204085a47..ee224f5fa4c 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java @@ -194,6 +194,7 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser, * @return the current URI location where the build is being performed * @since 5.1 */ + @Override public URI getWorkingDirectoryURI() { if (!fDirectoryStack.isEmpty()) return fDirectoryStack.lastElement(); diff --git a/xlc/org.eclipse.cdt.managedbuilder.xlc.core/src/org/eclipse/cdt/managedbuilder/xlc/core/XlcBuiltinSpecsDetector.java b/xlc/org.eclipse.cdt.managedbuilder.xlc.core/src/org/eclipse/cdt/managedbuilder/xlc/core/XlcBuiltinSpecsDetector.java index bea9e94d56f..2530eb4cb2c 100644 --- a/xlc/org.eclipse.cdt.managedbuilder.xlc.core/src/org/eclipse/cdt/managedbuilder/xlc/core/XlcBuiltinSpecsDetector.java +++ b/xlc/org.eclipse.cdt.managedbuilder.xlc.core/src/org/eclipse/cdt/managedbuilder/xlc/core/XlcBuiltinSpecsDetector.java @@ -64,7 +64,7 @@ public class XlcBuiltinSpecsDetector extends ToolchainBuiltinSpecsDetector imple } @Override - protected List parseForOptions(String line) { + protected List parseOptions(String line) { List options = new ArrayList(); Matcher optionMatcher = OPTIONS_PATTERN.matcher(line); while (optionMatcher.find()) {