1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 433171 - Handle line continuations when parsing build output

Change-Id: I9449e3167eae1464d23948da80663997adf95b16
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-03-09 02:56:12 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent 676f150755
commit ff5a55388c
2 changed files with 89 additions and 0 deletions

View file

@ -1130,6 +1130,51 @@ public class GCCBuildCommandParserTest extends BaseTestCase {
}
}
/**
* Test use of a line-continuation character ('\') in build output.
*/
public void testLineContinuation() throws Exception {
// Create model project and accompanied descriptions
String projectName = getName();
IProject project = ResourceHelper.createCDTProjectWithConfig(projectName);
ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project);
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
IFile file0=ResourceHelper.createFile(project, "file0.cpp");
IFile file1=ResourceHelper.createFile(project, "file1.cpp");
IFile file2=ResourceHelper.createFile(project, "file2.cpp");
ICLanguageSetting ls = cfgDescription.getLanguageSettingForFile(file0.getProjectRelativePath(), true);
String languageId = ls.getLanguageId();
// create GCCBuildCommandParser
GCCBuildCommandParser parser = (GCCBuildCommandParser) LanguageSettingsManager.getExtensionProviderCopy(GCC_BUILD_COMMAND_PARSER_EXT, true);
// parse line
parser.startup(cfgDescription, null);
parser.processLine("gcc file0.cpp -I/path0 \\");
parser.processLine(" -I/path1");
parser.processLine("gcc file1.cpp -I/path0 \\\\"); // not a continuation, '\' is escaped!
parser.processLine(" -I/path1");
parser.processLine("gcc file2.cpp -I/path0 \\"); // continuation at end of last line
parser.shutdown();
// check populated entries
{
List<ICLanguageSettingEntry> entries = parser.getSettingEntries(cfgDescription, file0, languageId);
assertEquals(new CIncludePathEntry("/path0", 0), entries.get(0));
assertEquals(new CIncludePathEntry("/path1", 0), entries.get(1));
}
{
List<ICLanguageSettingEntry> entries = parser.getSettingEntries(cfgDescription, file1, languageId);
assertEquals(new CIncludePathEntry("/path0", 0), entries.get(0));
assertEquals(1, entries.size());
}
{
List<ICLanguageSettingEntry> entries = parser.getSettingEntries(cfgDescription, file2, languageId);
assertEquals(new CIncludePathEntry("/path0", 0), entries.get(0));
}
}
/**
* Test parsing of paths located on a different drive on Windows.
*/

View file

@ -71,6 +71,9 @@ public abstract class AbstractBuildCommandParser extends AbstractLanguageSetting
// cached value from properties, do not need to use in equals() and hashCode()
private ResourceScope resourceScope = null;
// Used to handle line continuations in the build output.
private String partialLine;
/**
* The compiler command pattern without specifying compiler options.
* The options are intended to be handled with option parsers,
@ -241,10 +244,51 @@ public abstract class AbstractBuildCommandParser extends AbstractLanguageSetting
@Override
public void shutdown() {
// If there's an unprocessed partial line (because the last line of the build output ended
// in a line-continuation character), process it.
if (partialLine != null) {
processLine(partialLine);
partialLine = null;
}
serializeLanguageSettingsInBackground();
super.shutdown();
}
@Override
public boolean processLine(String line) {
line = handleLineContinuation(line);
return super.processLine(line);
}
/**
* Handle line continuations ('\' at the end of a line, indicating that the next line is a
* continuation of this one).
*/
private String handleLineContinuation(String line) {
if (line == null)
return null;
// If the character preceding the '\' is also '\', it's not a line continuation -
// the first '\' escapes the second.
if (line.length() > 0 && line.charAt(line.length() - 1) == '\\' &&
(line.length() == 1 || line.charAt(line.length() - 2) != '\\')) {
// Line ends in line continuation - save it for later.
String fragment = line.substring(0, line.length() - 1);
if (partialLine == null) {
partialLine = fragment;
} else {
partialLine += fragment;
}
return null; // line will not be processed now
} else if (partialLine != null) {
// Line doesn't end in continuation but previous lines did - use their contents.
line = partialLine + line;
partialLine = null;
}
return line;
}
/**
* Trivial Error Parser which allows highlighting of output lines matching the patterns
* of this parser. Intended for better troubleshooting experience.