mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42: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:
parent
676f150755
commit
ff5a55388c
2 changed files with 89 additions and 0 deletions
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -70,6 +70,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.
|
||||
|
@ -241,9 +244,50 @@ 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
|
||||
|
|
Loading…
Add table
Reference in a new issue