1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-06 17:26:01 +02:00

Resource scope for Build Command Parsers

This commit is contained in:
Andrew Gvozdev 2012-04-09 17:55:05 -04:00
parent d1e9395955
commit 0755f5870d
3 changed files with 211 additions and 13 deletions

View file

@ -195,6 +195,7 @@ public class GCCBuildCommandParserTest extends BaseTestCase {
assertEquals(null, provider.getLanguageScope()); assertEquals(null, provider.getLanguageScope());
assertEquals(null, provider.getSettingEntries(null, null, null)); assertEquals(null, provider.getSettingEntries(null, null, null));
assertEquals("", provider.getCompilerPattern()); assertEquals("", provider.getCompilerPattern());
assertEquals(AbstractBuildCommandParser.ResourceScope.FILE, provider.getResourceScope());
} }
{ {
@ -218,6 +219,8 @@ public class GCCBuildCommandParserTest extends BaseTestCase {
// setters // setters
provider.setCompilerPattern(CUSTOM_PARAMETER_2); provider.setCompilerPattern(CUSTOM_PARAMETER_2);
assertEquals(CUSTOM_PARAMETER_2, provider.getCompilerPattern()); assertEquals(CUSTOM_PARAMETER_2, provider.getCompilerPattern());
provider.setResourceScope(AbstractBuildCommandParser.ResourceScope.PROJECT);
assertEquals(AbstractBuildCommandParser.ResourceScope.PROJECT, provider.getResourceScope());
} }
} }
@ -236,11 +239,23 @@ public class GCCBuildCommandParserTest extends BaseTestCase {
// configure provider // configure provider
parser.setResolvingPaths(false); parser.setResolvingPaths(false);
assertFalse(parser.equals(clone0)); assertFalse(parser.equals(clone0));
parser.setResourceScope(AbstractBuildCommandParser.ResourceScope.PROJECT);
assertEquals(AbstractBuildCommandParser.ResourceScope.PROJECT, parser.getResourceScope());
parser.setResourceScope(AbstractBuildCommandParser.ResourceScope.FOLDER);
assertEquals(AbstractBuildCommandParser.ResourceScope.FOLDER, parser.getResourceScope());
parser.setResourceScope(AbstractBuildCommandParser.ResourceScope.FILE);
assertEquals(AbstractBuildCommandParser.ResourceScope.FILE, parser.getResourceScope());
// check another clone after configuring // check another clone after changing settings
{ {
parser.setResolvingPaths(false);
assertFalse(parser.equals(clone0));
parser.setResourceScope(AbstractBuildCommandParser.ResourceScope.PROJECT);
assertEquals(AbstractBuildCommandParser.ResourceScope.PROJECT, parser.getResourceScope());
MockBuildCommandParser clone = parser.clone(); MockBuildCommandParser clone = parser.clone();
assertTrue(parser.equals(clone)); assertTrue(parser.equals(clone));
assertEquals(parser.isResolvingPaths(), clone.isResolvingPaths());
assertEquals(parser.getResourceScope(), clone.getResourceScope());
} }
// check 'expand relative paths' flag // check 'expand relative paths' flag
@ -251,6 +266,16 @@ public class GCCBuildCommandParserTest extends BaseTestCase {
assertFalse(parser.equals(clone)); assertFalse(parser.equals(clone));
} }
// check resource scope
{
parser.setResourceScope(AbstractBuildCommandParser.ResourceScope.PROJECT);
assertEquals(AbstractBuildCommandParser.ResourceScope.PROJECT, parser.getResourceScope());
MockBuildCommandParser clone = parser.clone();
assertEquals(AbstractBuildCommandParser.ResourceScope.PROJECT, clone.getResourceScope());
clone.setResourceScope(AbstractBuildCommandParser.ResourceScope.FOLDER);
assertFalse(parser.equals(clone));
}
// check cloneShallow() // check cloneShallow()
{ {
MockBuildCommandParser parser2 = parser.clone(); MockBuildCommandParser parser2 = parser.clone();

View file

@ -21,6 +21,10 @@ import org.eclipse.cdt.core.IMarkerGenerator;
import org.eclipse.cdt.core.errorparsers.RegexErrorParser; import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern; import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsLogger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
/** /**
* Abstract class for providers parsing compiler option from build command when present in build output. * Abstract class for providers parsing compiler option from build command when present in build output.
@ -29,12 +33,24 @@ import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
*/ */
public abstract class AbstractBuildCommandParser extends AbstractLanguageSettingsOutputScanner { public abstract class AbstractBuildCommandParser extends AbstractLanguageSettingsOutputScanner {
public static final Object JOB_FAMILY_BUILD_COMMAND_PARSER = "org.eclipse.cdt.managedbuilder.AbstractBuildCommandParser"; //$NON-NLS-1$ public static final Object JOB_FAMILY_BUILD_COMMAND_PARSER = "org.eclipse.cdt.managedbuilder.AbstractBuildCommandParser"; //$NON-NLS-1$
private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$ private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$
private static final String ATTR_RESOURCE_SCOPE = "resource-scope"; //$NON-NLS-1$
private static final String VALUE_FILE_SCOPE = "per-file"; //$NON-NLS-1$
private static final String VALUE_FOLDER_SCOPE = "per-folder"; //$NON-NLS-1$
private static final String VALUE_PROJECT_SCOPE = "per-project"; //$NON-NLS-1$
private static final String LEADING_PATH_PATTERN = "\\S+[/\\\\]"; //$NON-NLS-1$ private static final String LEADING_PATH_PATTERN = "\\S+[/\\\\]"; //$NON-NLS-1$
private static final Pattern OPTIONS_PATTERN = Pattern.compile("-[^\\s\"']*(\\s*((\".*?\")|('.*?')|([^-\\s][^\\s]+)))?"); //$NON-NLS-1$ private static final Pattern OPTIONS_PATTERN = Pattern.compile("-[^\\s\"']*(\\s*((\".*?\")|('.*?')|([^-\\s][^\\s]+)))?"); //$NON-NLS-1$
private static final int OPTION_GROUP = 0; private static final int OPTION_GROUP = 0;
public enum ResourceScope {
FILE,
FOLDER,
PROJECT,
}
/** /**
* Note: design patterns to keep file group the same and matching {@link #FILE_GROUP} * Note: design patterns to keep file group the same and matching {@link #FILE_GROUP}
*/ */
@ -45,6 +61,8 @@ public abstract class AbstractBuildCommandParser extends AbstractLanguageSetting
}; };
private static final int FILE_GROUP = 2; private static final int FILE_GROUP = 2;
// cached value from properties, do not need to use in equals() and hashCode()
private ResourceScope resourceScope = null;
/** /**
* The compiler command pattern without specifying compiler options. * The compiler command pattern without specifying compiler options.
@ -76,6 +94,85 @@ public abstract class AbstractBuildCommandParser extends AbstractLanguageSetting
return "\\s*\"?("+LEADING_PATH_PATTERN+")?(" + compilerPattern + ")\"?"; return "\\s*\"?("+LEADING_PATH_PATTERN+")?(" + compilerPattern + ")\"?";
} }
/**
* @return resource scope of the entries, i.e. level in resource hierarchy where language settings entries
* will be applied by the provider. Resource scope can be one of the following:
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FILE} - apply entries to the file being parsed.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FOLDER} - apply entries to the enclosing folder.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.PROJECT} - apply entries to the project level.
*/
public ResourceScope getResourceScope() {
if (resourceScope == null) {
String scopeStr = getProperty(ATTR_RESOURCE_SCOPE);
if (scopeStr.equals(VALUE_FILE_SCOPE)) {
resourceScope = ResourceScope.FILE;
} else if (scopeStr.equals(VALUE_FOLDER_SCOPE)) {
resourceScope = ResourceScope.FOLDER;
} else if (scopeStr.equals(VALUE_PROJECT_SCOPE)) {
resourceScope = ResourceScope.PROJECT;
} else {
resourceScope = ResourceScope.FILE;
}
}
return resourceScope;
}
/**
* Set resource scope of the entries, i.e. level in resource hierarchy where language settings entries
* will be applied by the provider.
*
* @param rcScope - resource scope can be one of the following:
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FILE} - apply entries to the file being parsed.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.FOLDER} - apply entries to the enclosing folder.
* <br>- {@code AbstractBuildCommandParser.ResourceScope.PROJECT} - apply entries to the project level.
*/
public void setResourceScope(ResourceScope rcScope) {
resourceScope = rcScope;
switch (rcScope) {
case FILE:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_FILE_SCOPE);
break;
case FOLDER:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_FOLDER_SCOPE);
break;
case PROJECT:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_PROJECT_SCOPE);
break;
default:
setProperty(ATTR_RESOURCE_SCOPE, VALUE_FILE_SCOPE);
break;
}
}
@Override
protected void setSettingEntries(List<ICLanguageSettingEntry> entries) {
IResource rc = null;
switch (getResourceScope()) {
case FILE:
rc = currentResource;
break;
case FOLDER:
if (currentResource instanceof IFile) {
rc = currentResource.getParent();
}
break;
case PROJECT:
if (currentResource != null) {
rc = currentResource.getProject();
}
break;
default:
break;
}
setSettingEntries(currentCfgDescription, rc, currentLanguageId, entries);
// AG FIXME - temporary log to remove before CDT Juno release
LanguageSettingsLogger.logInfo(getPrefixForLog()
+ getClass().getSimpleName() + " collected " + (entries!=null ? ("" + entries.size()) : "null") + " entries for " + rc);
}
/** /**
* Adjust count for file group taking into consideration extra groups added by {@link #getCompilerPatternExtended()}. * Adjust count for file group taking into consideration extra groups added by {@link #getCompilerPatternExtended()}.
*/ */

View file

@ -30,6 +30,7 @@ import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
@ -46,7 +47,10 @@ public final class GCCBuildCommandParserOptionPage extends AbstractLanguageSetti
private Button runOnceRadioButton; private Button runOnceRadioButton;
private Button runEveryBuildRadioButton; private Button runEveryBuildRadioButton;
private Button expandRelativePathCheckBox; private Button expandRelativePathCheckBox;
private Button applyToProjectCheckBox;
private Button scopeProjectRadioButton;
private Button scopeFolderRadioButton;
private Button scopeFileRadioButton;
/* /*
@ -157,25 +161,97 @@ public final class GCCBuildCommandParserOptionPage extends AbstractLanguageSetti
} }
Group resourceScopeGroup = new Group(composite, SWT.NONE);
{ {
applyToProjectCheckBox = new Button(composite, SWT.CHECK); // resourceScopeGroup.setText("Define scope of discovered entries");
applyToProjectCheckBox.setText("Apply discovered settings on project level"); // resourceScopeGroup.setText("Apply discovered entries to");
resourceScopeGroup.setText("Scope to keep discovered entries");
resourceScopeGroup.setLayout(new GridLayout(2, false));
GridData gd = new GridData(GridData.FILL_HORIZONTAL); GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2; gd.horizontalSpan = 2;
applyToProjectCheckBox.setLayoutData(gd); resourceScopeGroup.setLayoutData(gd);
}
// applyToProjectCheckBox.setSelection(provider.isExpandRelativePaths()); {
// applyToProjectCheckBox.setEnabled(fEditable); scopeFileRadioButton = new Button(resourceScopeGroup, SWT.RADIO);
applyToProjectCheckBox.setSelection(false); scopeFileRadioButton.setText("Per file, use when settings vary for different files");
applyToProjectCheckBox.setEnabled(false); // applyToResourceRadioButton.setText("File level, use when settings vary for different files");
applyToProjectCheckBox.addSelectionListener(new SelectionAdapter() { GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
scopeFileRadioButton.setLayoutData(gd);
scopeFileRadioButton.setSelection(provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FILE);
scopeFileRadioButton.setEnabled(fEditable);
scopeFileRadioButton.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) {
boolean enabled = applyToProjectCheckBox.getSelection(); boolean enabled = scopeFileRadioButton.getSelection();
AbstractBuildCommandParser provider = getRawProvider(); AbstractBuildCommandParser provider = getRawProvider();
if (enabled != provider.isResolvingPaths()) { if (enabled != (provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FILE)) {
AbstractBuildCommandParser selectedProvider = getWorkingCopy(providerId); AbstractBuildCommandParser selectedProvider = getWorkingCopy(providerId);
selectedProvider.setResolvingPaths(enabled); selectedProvider.setResourceScope(AbstractBuildCommandParser.ResourceScope.FILE);
providerTab.refreshItem(selectedProvider);
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
{
scopeFolderRadioButton = new Button(resourceScopeGroup, SWT.RADIO);
scopeFolderRadioButton.setText("Per folder, use when settings are the same for all files in a folder");
// applyToEnclosingFolderRadioButton.setText("Enclosing folder, use when settings are the same for all files in a folder");
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
scopeFolderRadioButton.setLayoutData(gd);
scopeFolderRadioButton.setSelection(provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FOLDER);
scopeFolderRadioButton.setEnabled(fEditable);
scopeFolderRadioButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean enabled = scopeFolderRadioButton.getSelection();
AbstractBuildCommandParser provider = getRawProvider();
if (enabled != (provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FOLDER)) {
AbstractBuildCommandParser selectedProvider = getWorkingCopy(providerId);
selectedProvider.setResourceScope(AbstractBuildCommandParser.ResourceScope.FOLDER);
providerTab.refreshItem(selectedProvider);
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
{
scopeProjectRadioButton = new Button(resourceScopeGroup, SWT.RADIO);
scopeProjectRadioButton.setText("Per project, use when settings are the same for all files in the project");
// applyToProjectRadioButton.setText("Project level, use when settings are the same for all files in the project");
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
scopeProjectRadioButton.setLayoutData(gd);
scopeProjectRadioButton.setSelection(provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.PROJECT);
scopeProjectRadioButton.setEnabled(fEditable);
scopeProjectRadioButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean enabled = scopeProjectRadioButton.getSelection();
AbstractBuildCommandParser provider = getRawProvider();
if (enabled != (provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.PROJECT)) {
AbstractBuildCommandParser selectedProvider = getWorkingCopy(providerId);
selectedProvider.setResourceScope(AbstractBuildCommandParser.ResourceScope.PROJECT);
providerTab.refreshItem(selectedProvider); providerTab.refreshItem(selectedProvider);
} }
} }