blob: 57b433e9e610250e613fb551afa15b01ac82078f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jesper S Møller - Bug 529432 - Allow JDT UI to target Java 10
*******************************************************************************/
package org.eclipse.jdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.osgi.service.prefs.Preferences;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.preferences.BundleDefaultsScope;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstall2;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
/**
* Configuration block for the 'Java Compiler' page.
*/
public class ComplianceConfigurationBlock extends OptionsConfigurationBlock {
/**
* Key for the "Compiler compliance follows EE" setting.
* <br>Only applicable if <code>fProject != null</code>.
* <p>Values are { {@link #DEFAULT_CONF}, {@link #USER_CONF}, or {@link #DISABLED} }.
*/
private static final Key INTR_COMPLIANCE_FOLLOWS_EE= getLocalKey("internal.compliance.follows.ee"); //$NON-NLS-1$
/**
* Key for the "Use default compliance" setting.
* <p>Values are { {@link #DEFAULT_CONF}, {@link #USER_CONF} }.
*/
private static final Key INTR_DEFAULT_COMPLIANCE= getLocalKey("internal.default.compliance"); //$NON-NLS-1$
// Preference store keys, see JavaCore.getOptions
private static final Key PREF_PB_ASSERT_AS_IDENTIFIER= getJDTCoreKey(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER);
private static final Key PREF_PB_ENUM_AS_IDENTIFIER= getJDTCoreKey(JavaCore.COMPILER_PB_ENUM_IDENTIFIER);
private static final Key PREF_SOURCE_COMPATIBILITY= getJDTCoreKey(JavaCore.COMPILER_SOURCE);
private static final Key PREF_CODEGEN_TARGET_PLATFORM= getJDTCoreKey(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM);
private static final Key PREF_COMPLIANCE= getJDTCoreKey(JavaCore.COMPILER_COMPLIANCE);
private static final Key PREF_RELEASE= getJDTCoreKey(JavaCore.COMPILER_RELEASE);
private static final Key PREF_ENABLE_PREVIEW= getJDTCoreKey(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES);
private static final Key PREF_PB_REPORT_PREVIEW= getJDTCoreKey(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES);
/* see also BuildPathSupport#PREFS_COMPLIANCE */
private static final Key[] PREFS_COMPLIANCE= new Key[] { PREF_COMPLIANCE,
PREF_PB_ASSERT_AS_IDENTIFIER, PREF_PB_ENUM_AS_IDENTIFIER,
PREF_SOURCE_COMPATIBILITY, PREF_CODEGEN_TARGET_PLATFORM};
private static final Key[] PREFS_COMPLIANCE_11_OR_HIGHER= new Key[] { PREF_COMPLIANCE,
PREF_PB_ASSERT_AS_IDENTIFIER, PREF_PB_ENUM_AS_IDENTIFIER,
PREF_SOURCE_COMPATIBILITY, PREF_CODEGEN_TARGET_PLATFORM,
PREF_ENABLE_PREVIEW, PREF_PB_REPORT_PREVIEW};
private static final Key PREF_CODEGEN_INLINE_JSR_BYTECODE= getJDTCoreKey(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE);
private static final Key PREF_LOCAL_VARIABLE_ATTR= getJDTCoreKey(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR);
private static final Key PREF_LINE_NUMBER_ATTR= getJDTCoreKey(JavaCore.COMPILER_LINE_NUMBER_ATTR);
private static final Key PREF_SOURCE_FILE_ATTR= getJDTCoreKey(JavaCore.COMPILER_SOURCE_FILE_ATTR);
private static final Key PREF_CODEGEN_UNUSED_LOCAL= getJDTCoreKey(JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL);
private static final Key PREF_CODEGEN_METHOD_PARAMETERS_ATTR= getJDTCoreKey(JavaCore.COMPILER_CODEGEN_METHOD_PARAMETERS_ATTR);
// values
private static final String GENERATE= JavaCore.GENERATE;
private static final String DO_NOT_GENERATE= JavaCore.DO_NOT_GENERATE;
private static final String PRESERVE= JavaCore.PRESERVE;
private static final String OPTIMIZE_OUT= JavaCore.OPTIMIZE_OUT;
private static final String VERSION_CLDC_1_1= JavaCore.VERSION_CLDC_1_1;
private static final String VERSION_1_1= JavaCore.VERSION_1_1;
private static final String VERSION_1_2= JavaCore.VERSION_1_2;
private static final String VERSION_1_3= JavaCore.VERSION_1_3;
private static final String VERSION_1_4= JavaCore.VERSION_1_4;
private static final String VERSION_1_5= JavaCore.VERSION_1_5;
private static final String VERSION_1_6= JavaCore.VERSION_1_6;
private static final String VERSION_1_7= JavaCore.VERSION_1_7;
private static final String VERSION_1_8= JavaCore.VERSION_1_8;
private static final String VERSION_9= JavaCore.VERSION_9;
private static final String VERSION_10= JavaCore.VERSION_10;
private static final String VERSION_11= JavaCore.VERSION_11;
private static final String VERSION_12 = JavaCore.VERSION_12;
private static final String VERSION_13 = JavaCore.VERSION_13;
private static final String VERSION_14 = JavaCore.VERSION_14;
private static final String VERSION_15 = JavaCore.VERSION_15;
private static final String VERSION_16 = JavaCore.VERSION_16;
private static final String VERSION_17 = JavaCore.VERSION_17;
private static final String VERSION_LATEST = JavaCore.latestSupportedJavaVersion();
private static final String VERSION_JSR14= "jsr14"; //$NON-NLS-1$
private static final String ERROR= JavaCore.ERROR;
private static final String WARNING= JavaCore.WARNING;
private static final String INFO= JavaCore.INFO;
private static final String IGNORE= JavaCore.IGNORE;
private static final String ENABLED= JavaCore.ENABLED;
private static final String DISABLED= JavaCore.DISABLED;
private static final String DEFAULT_CONF= "default"; //$NON-NLS-1$
private static final String USER_CONF= "user"; //$NON-NLS-1$
private ArrayList<Control> fComplianceFollowsEEControls;
private ArrayList<Control> fComplianceControls;
private ArrayList<Control> fComplianceChildControls;
private PixelConverter fPixelConverter;
/**
* Remembered user compliance (stored when {@link #INTR_DEFAULT_COMPLIANCE} is switched to
* {@link #DEFAULT_CONF}). Elements are identified by <code>IDX_*</code> constants.
*
* @see #IDX_ASSERT_AS_IDENTIFIER
* @see #IDX_ENUM_AS_IDENTIFIER
* @see #IDX_SOURCE_COMPATIBILITY
* @see #IDX_CODEGEN_TARGET_PLATFORM
* @see #IDX_COMPLIANCE
* @see #IDX_INLINE_JSR_BYTECODE
* @see #IDX_METHOD_PARAMETERS_ATTR
* @see #IDX_RELEASE
* @see #IDX_ENABLE_PREVIEW
* @see #IDX_REPORT_PREVIEW
*/
private String[] fRememberedUserCompliance;
/**
* Stored compliance settings that were active when the page was first shown. May be
* <code>null</code>. Elements are identified by <code>IDX_*</code> constants.
*
* @see #IDX_ASSERT_AS_IDENTIFIER
* @see #IDX_ENUM_AS_IDENTIFIER
* @see #IDX_SOURCE_COMPATIBILITY
* @see #IDX_CODEGEN_TARGET_PLATFORM
* @see #IDX_COMPLIANCE
* @see #IDX_INLINE_JSR_BYTECODE
* @see #IDX_METHOD_PARAMETERS_ATTR
* @see #IDX_RELEASE
* @see #IDX_ENABLE_PREVIEW
* @see #IDX_REPORT_PREVIEW
*/
private String[] fOriginalStoredCompliance;
private static final int IDX_ASSERT_AS_IDENTIFIER= 0;
private static final int IDX_ENUM_AS_IDENTIFIER= 1;
private static final int IDX_SOURCE_COMPATIBILITY= 2;
private static final int IDX_CODEGEN_TARGET_PLATFORM= 3;
private static final int IDX_COMPLIANCE= 4;
private static final int IDX_INLINE_JSR_BYTECODE= 5;
private static final int IDX_METHOD_PARAMETERS_ATTR= 6;
private static final int IDX_RELEASE= 7;
private static final int IDX_ENABLE_PREVIEW= 8;
private static final int IDX_REPORT_PREVIEW= 9;
private IStatus fComplianceStatus;
private Link fJRE50InfoText;
private Label fJRE50InfoImage;
private Composite fControlsComposite;
private ControlEnableState fBlockEnableState;
private Button fCompilerReleaseCheck;
private Button fEnablePreviewCheck;
private Combo fReportPreviewCombo;
public ComplianceConfigurationBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) {
super(context, project, getKeys(project != null), container);
setDefaultCompilerComplianceValues();
fBlockEnableState= null;
fComplianceFollowsEEControls= new ArrayList<>();
fComplianceControls= new ArrayList<>();
fComplianceChildControls= new ArrayList<>();
fComplianceStatus= new StatusInfo();
fRememberedUserCompliance= new String[] { // caution: order depends on IDX_* constants
getValue(PREF_PB_ASSERT_AS_IDENTIFIER),
getValue(PREF_PB_ENUM_AS_IDENTIFIER),
getValue(PREF_SOURCE_COMPATIBILITY),
getValue(PREF_CODEGEN_TARGET_PLATFORM),
getValue(PREF_COMPLIANCE),
getValue(PREF_CODEGEN_INLINE_JSR_BYTECODE),
getValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR),
getValue(PREF_RELEASE),
getValue(PREF_ENABLE_PREVIEW),
getValue(PREF_PB_REPORT_PREVIEW)
};
}
public static Key[] getKeys(boolean projectSpecific) {
Key[] keys= new Key[] {
PREF_LOCAL_VARIABLE_ATTR, PREF_LINE_NUMBER_ATTR, PREF_SOURCE_FILE_ATTR, PREF_CODEGEN_UNUSED_LOCAL, PREF_CODEGEN_INLINE_JSR_BYTECODE, INTR_DEFAULT_COMPLIANCE,
PREF_COMPLIANCE, PREF_SOURCE_COMPATIBILITY,
PREF_CODEGEN_TARGET_PLATFORM, PREF_PB_ASSERT_AS_IDENTIFIER, PREF_PB_ENUM_AS_IDENTIFIER, PREF_CODEGEN_METHOD_PARAMETERS_ATTR, PREF_RELEASE,
PREF_ENABLE_PREVIEW, PREF_PB_REPORT_PREVIEW
};
if (projectSpecific) {
Key[] allKeys = new Key[keys.length + 1];
System.arraycopy(keys, 0, allKeys, 0, keys.length);
allKeys[keys.length]= INTR_COMPLIANCE_FOLLOWS_EE;
return allKeys;
}
return keys;
}
@Override
protected void settingsUpdated() {
setValue(INTR_DEFAULT_COMPLIANCE, getCurrentCompliance());
updateComplianceFollowsEE();
super.settingsUpdated();
}
/*
* @see org.eclipse.jface.preference.PreferencePage#createContents(Composite)
*/
@Override
protected Control createContents(Composite parent) {
fPixelConverter= new PixelConverter(parent);
setShell(parent.getShell());
Composite complianceComposite= createComplianceTabContent(parent);
validateSettings(null, null, null);
return complianceComposite;
}
public void enablePreferenceContent(boolean enable) {
if (fControlsComposite != null && !fControlsComposite.isDisposed()) {
if (enable) {
if (fBlockEnableState != null) {
fBlockEnableState.restore();
fBlockEnableState= null;
}
} else {
if (fBlockEnableState == null) {
fBlockEnableState= ControlEnableState.disable(fControlsComposite);
}
}
}
}
private Composite createComplianceTabContent(Composite folder) {
final String[] complianceVersions= new String[] { VERSION_1_3, VERSION_1_4,
VERSION_1_5, VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14, VERSION_15, VERSION_16, VERSION_17 };
final String[] complianceLabels= new String[] {
PreferencesMessages.ComplianceConfigurationBlock_version13,
PreferencesMessages.ComplianceConfigurationBlock_version14,
PreferencesMessages.ComplianceConfigurationBlock_version15,
PreferencesMessages.ComplianceConfigurationBlock_version16,
PreferencesMessages.ComplianceConfigurationBlock_version17,
PreferencesMessages.ComplianceConfigurationBlock_version18,
PreferencesMessages.ComplianceConfigurationBlock_version9,
PreferencesMessages.ComplianceConfigurationBlock_version10,
PreferencesMessages.ComplianceConfigurationBlock_version_11,
PreferencesMessages.ComplianceConfigurationBlock_version_12,
PreferencesMessages.ComplianceConfigurationBlock_version_13,
PreferencesMessages.ComplianceConfigurationBlock_version_14,
PreferencesMessages.ComplianceConfigurationBlock_version_15,
PreferencesMessages.ComplianceConfigurationBlock_version_16,
PreferencesMessages.ComplianceConfigurationBlock_version_17,
};
String[] targetVersions= new String[] { VERSION_CLDC_1_1, VERSION_1_1, VERSION_1_2, VERSION_1_3, VERSION_1_4,
VERSION_1_5, VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14, VERSION_15, VERSION_16, VERSION_17 };
String[] targetLabels= new String[] {
PreferencesMessages.ComplianceConfigurationBlock_versionCLDC11,
PreferencesMessages.ComplianceConfigurationBlock_version11,
PreferencesMessages.ComplianceConfigurationBlock_version12,
PreferencesMessages.ComplianceConfigurationBlock_version13,
PreferencesMessages.ComplianceConfigurationBlock_version14,
PreferencesMessages.ComplianceConfigurationBlock_version15,
PreferencesMessages.ComplianceConfigurationBlock_version16,
PreferencesMessages.ComplianceConfigurationBlock_version17,
PreferencesMessages.ComplianceConfigurationBlock_version18,
PreferencesMessages.ComplianceConfigurationBlock_version9,
PreferencesMessages.ComplianceConfigurationBlock_version10,
PreferencesMessages.ComplianceConfigurationBlock_version_11,
PreferencesMessages.ComplianceConfigurationBlock_version_12,
PreferencesMessages.ComplianceConfigurationBlock_version_13,
PreferencesMessages.ComplianceConfigurationBlock_version_14,
PreferencesMessages.ComplianceConfigurationBlock_version_15,
PreferencesMessages.ComplianceConfigurationBlock_version_16,
PreferencesMessages.ComplianceConfigurationBlock_version_17,
};
if (ComplianceConfigurationBlock.VERSION_JSR14.equals(getValue(PREF_CODEGEN_TARGET_PLATFORM))) {
targetVersions= append(targetVersions, ComplianceConfigurationBlock.VERSION_JSR14);
targetLabels= append(targetLabels, ComplianceConfigurationBlock.VERSION_JSR14);
}
String[] sourceVersions= new String[] { VERSION_1_3, VERSION_1_4,
VERSION_1_5, VERSION_1_6, VERSION_1_7, VERSION_1_8, VERSION_9, VERSION_10, VERSION_11, VERSION_12, VERSION_13, VERSION_14, VERSION_15, VERSION_16, VERSION_17 };
String[] sourceLabels= new String[] {
PreferencesMessages.ComplianceConfigurationBlock_version13,
PreferencesMessages.ComplianceConfigurationBlock_version14,
PreferencesMessages.ComplianceConfigurationBlock_version15,
PreferencesMessages.ComplianceConfigurationBlock_version16,
PreferencesMessages.ComplianceConfigurationBlock_version17,
PreferencesMessages.ComplianceConfigurationBlock_version18,
PreferencesMessages.ComplianceConfigurationBlock_version9,
PreferencesMessages.ComplianceConfigurationBlock_version10,
PreferencesMessages.ComplianceConfigurationBlock_version_11,
PreferencesMessages.ComplianceConfigurationBlock_version_12,
PreferencesMessages.ComplianceConfigurationBlock_version_13,
PreferencesMessages.ComplianceConfigurationBlock_version_14,
PreferencesMessages.ComplianceConfigurationBlock_version_15,
PreferencesMessages.ComplianceConfigurationBlock_version_16,
PreferencesMessages.ComplianceConfigurationBlock_version_17,
};
final ScrolledPageContent sc1 = new ScrolledPageContent(folder);
Composite composite= sc1.getBody();
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
composite.setLayout(layout);
fControlsComposite= new Composite(composite, SWT.NONE);
fControlsComposite.setFont(composite.getFont());
fControlsComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.numColumns= 1;
fControlsComposite.setLayout(layout);
int nColumns= 3;
layout= new GridLayout();
layout.numColumns= nColumns;
Group group= new Group(fControlsComposite, SWT.NONE);
group.setFont(fControlsComposite.getFont());
group.setText(PreferencesMessages.ComplianceConfigurationBlock_compliance_group_label);
group.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
group.setLayout(layout);
String[] defaultUserValues= new String[] { DEFAULT_CONF, USER_CONF };
Control[] otherChildren= group.getChildren();
if (fProject != null) {
String label= PreferencesMessages.ComplianceConfigurationBlock_compliance_follows_EE_label;
int widthHint= fPixelConverter.convertWidthInCharsToPixels(40);
addCheckBoxWithLink(group, label, INTR_COMPLIANCE_FOLLOWS_EE, defaultUserValues, 0, widthHint, new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
openBuildPathPropertyPage();
}
});
}
Control[] allChildren= group.getChildren();
fComplianceFollowsEEControls.addAll(Arrays.asList(allChildren));
fComplianceFollowsEEControls.removeAll(Arrays.asList(otherChildren));
otherChildren= allChildren;
String label= PreferencesMessages.ComplianceConfigurationBlock_compiler_compliance_label;
addComboBox(group, label, PREF_COMPLIANCE, complianceVersions, complianceLabels, 0);
label= PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_backwardcompatibility_label;
fCompilerReleaseCheck= addCheckBox(group, label, PREF_RELEASE, new String[] { DISABLED, ENABLED }, 0, false);
label= PreferencesMessages.ComplianceConfigurationBlock_default_settings_label;
addCheckBox(group, label, INTR_DEFAULT_COMPLIANCE, defaultUserValues, 0);
allChildren= group.getChildren();
fComplianceControls.addAll(Arrays.asList(allChildren));
fComplianceControls.removeAll(Arrays.asList(otherChildren));
otherChildren= allChildren;
int indent= LayoutUtil.getIndent();
String[] warningInfoIgnore= new String[] { WARNING, INFO, IGNORE };
String[] warningInfoIgnoreLabels= new String[] {
PreferencesMessages.ComplianceConfigurationBlock_warning,
PreferencesMessages.ComplianceConfigurationBlock_info,
PreferencesMessages.ComplianceConfigurationBlock_ignore
};
label= Messages.format(PreferencesMessages.ComplianceConfigurationBlock_enable_preview_label, new String[] { getVersionLabel(VERSION_LATEST) });
fEnablePreviewCheck= addCheckBox(group, label, PREF_ENABLE_PREVIEW, new String[] { ENABLED, DISABLED }, indent);
label= PreferencesMessages.ComplianceConfigurationBlock_enable_preview_severity_label;
fReportPreviewCombo= addComboBox(group, label, PREF_PB_REPORT_PREVIEW, warningInfoIgnore, warningInfoIgnoreLabels, indent * 2);
fReportPreviewCombo.setEnabled(fEnablePreviewCheck.isEnabled() && fEnablePreviewCheck.getSelection());
label= PreferencesMessages.ComplianceConfigurationBlock_codegen_targetplatform_label;
addComboBox(group, label, PREF_CODEGEN_TARGET_PLATFORM, targetVersions, targetLabels, indent);
label= PreferencesMessages.ComplianceConfigurationBlock_source_compatibility_label;
addComboBox(group, label, PREF_SOURCE_COMPATIBILITY, sourceVersions, sourceLabels, indent);
String[] errorWarningInfoIgnore= new String[] { ERROR, WARNING, INFO, IGNORE };
String[] errorWarningInfoIgnoreLabels= new String[] {
PreferencesMessages.ComplianceConfigurationBlock_error,
PreferencesMessages.ComplianceConfigurationBlock_warning,
PreferencesMessages.ComplianceConfigurationBlock_info,
PreferencesMessages.ComplianceConfigurationBlock_ignore
};
label= PreferencesMessages.ComplianceConfigurationBlock_pb_assert_as_identifier_label;
addComboBox(group, label, PREF_PB_ASSERT_AS_IDENTIFIER, errorWarningInfoIgnore, errorWarningInfoIgnoreLabels, indent);
label= PreferencesMessages.ComplianceConfigurationBlock_pb_enum_as_identifier_label;
addComboBox(group, label, PREF_PB_ENUM_AS_IDENTIFIER, errorWarningInfoIgnore, errorWarningInfoIgnoreLabels, indent);
allChildren= group.getChildren();
fComplianceChildControls.addAll(Arrays.asList(allChildren));
fComplianceChildControls.removeAll(Arrays.asList(otherChildren));
layout= new GridLayout();
layout.numColumns= nColumns;
group= new Group(fControlsComposite, SWT.NONE);
group.setFont(fControlsComposite.getFont());
group.setText(PreferencesMessages.ComplianceConfigurationBlock_classfiles_group_label);
group.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
group.setLayout(layout);
String[] generateValues= new String[] { GENERATE, DO_NOT_GENERATE };
String[] enableDisableValues= new String[] { ENABLED, DISABLED };
label= PreferencesMessages.ComplianceConfigurationBlock_variable_attr_label;
addCheckBox(group, label, PREF_LOCAL_VARIABLE_ATTR, generateValues, 0);
label= PreferencesMessages.ComplianceConfigurationBlock_line_number_attr_label;
addCheckBox(group, label, PREF_LINE_NUMBER_ATTR, generateValues, 0);
label= PreferencesMessages.ComplianceConfigurationBlock_source_file_attr_label;
addCheckBox(group, label, PREF_SOURCE_FILE_ATTR, generateValues, 0);
label= PreferencesMessages.ComplianceConfigurationBlock_codegen_unused_local_label;
addCheckBox(group, label, PREF_CODEGEN_UNUSED_LOCAL, new String[] { PRESERVE, OPTIMIZE_OUT }, 0);
label= PreferencesMessages.ComplianceConfigurationBlock_codegen_inline_jsr_bytecode_label;
addCheckBox(group, label, PREF_CODEGEN_INLINE_JSR_BYTECODE, enableDisableValues, 0);
label= PreferencesMessages.ComplianceConfigurationBlock_codegen_method_parameters_attr;
addCheckBox(group, label, PREF_CODEGEN_METHOD_PARAMETERS_ATTR, generateValues, 0);
Composite infoComposite= new Composite(fControlsComposite, SWT.NONE);
infoComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
infoComposite.setLayout(new GridLayout(2, false));
fJRE50InfoImage= new Label(infoComposite, SWT.NONE);
fJRE50InfoImage.setImage(JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING));
GridData gd= new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false);
fJRE50InfoImage.setLayoutData(gd);
fJRE50InfoText= new Link(infoComposite, SWT.WRAP);
fJRE50InfoText.setFont(composite.getFont());
// set a text: not the real one, just for layouting
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info_project, new String[] { getVersionLabel(VERSION_1_3), getVersionLabel(VERSION_1_3) }));
fJRE50InfoText.setVisible(false);
fJRE50InfoText.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
if ("1".equals(e.text)) { //$NON-NLS-1$
openJREInstallPreferencePage(false);
} else if ("2".equals(e.text)) { //$NON-NLS-1$
openJREInstallPreferencePage(true);
} else {
openBuildPathPropertyPage();
}
}
@Override
public void widgetSelected(SelectionEvent e) {
widgetDefaultSelected(e);
}
});
gd= new GridData(GridData.FILL, GridData.FILL, true, true);
gd.widthHint= fPixelConverter.convertWidthInCharsToPixels(50);
fJRE50InfoText.setLayoutData(gd);
initializeReleaseCheckBox(false);
updateReleaseOptionStatus();
validateComplianceStatus();
return sc1;
}
private void initializeReleaseCheckBox(boolean useProjectSpecificSettings) {
if (fProject != null && !useProjectSpecificSettings) {
String value= PREF_RELEASE.getStoredValue(new IScopeContext[] { new ProjectScope(fProject) }, false, null);
if (value != null) {
setValue(PREF_RELEASE, value);
fCompilerReleaseCheck.setSelection(DISABLED.equals(value) ? false : true);
} else {
setValue(PREF_RELEASE, DISABLED);
fCompilerReleaseCheck.setSelection(false);
}
} else {
String value= PREF_RELEASE.getStoredValue(new IScopeContext[] { InstanceScope.INSTANCE }, false, null);
if (value != null) {
setValue(PREF_RELEASE, value);
fCompilerReleaseCheck.setSelection(DISABLED.equals(value) ? false : true);
} else {
setValue(PREF_RELEASE, DISABLED);
fCompilerReleaseCheck.setSelection(false);
}
}
}
private static String[] append(String[] versions, String version) {
String[] result= new String[versions.length + 1];
System.arraycopy(versions, 0, result, 0, versions.length);
result[versions.length]= version;
return result;
}
protected final void openBuildPathPropertyPage() {
if (getPreferenceContainer() != null) {
Map<Object, IClasspathEntry> data= new HashMap<>();
data.put(BuildPathsPropertyPage.DATA_REVEAL_ENTRY, JavaRuntime.getDefaultJREContainerEntry());
getPreferenceContainer().openPage(BuildPathsPropertyPage.PROP_ID, data);
}
updateReleaseOptionStatus();
validateComplianceStatus();
}
protected final void openJREInstallPreferencePage(boolean openEE) {
String jreID= BuildPathSupport.JRE_PREF_PAGE_ID;
String eeID= BuildPathSupport.EE_PREF_PAGE_ID;
String pageId= openEE ? eeID : jreID;
if (fProject == null && getPreferenceContainer() != null) {
getPreferenceContainer().openPage(pageId, null);
} else {
PreferencesUtil.createPreferenceDialogOn(getShell(), pageId, new String[] { jreID, eeID }, null).open();
}
updateReleaseOptionStatus();
validateComplianceStatus();
}
@Override
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
if (!areSettingsEnabled()) {
return;
}
if (changedKey != null) {
if (INTR_DEFAULT_COMPLIANCE.equals(changedKey)) {
updateComplianceEnableState();
updateComplianceDefaultSettings(true, null);
fComplianceStatus= validateCompliance();
} else if (INTR_COMPLIANCE_FOLLOWS_EE.equals(changedKey)) {
setValue(INTR_DEFAULT_COMPLIANCE, DEFAULT_CONF);
updateReleaseOptionStatus();
updateComplianceEnableState();
updateComplianceDefaultSettings(true, null);
updateControls();
fComplianceStatus= validateCompliance();
validateComplianceStatus();
} else if (PREF_COMPLIANCE.equals(changedKey)) {
updateReleaseOptionStatus();
// set compliance settings to default
Object oldDefault= getValue(INTR_DEFAULT_COMPLIANCE);
boolean rememberOld= USER_CONF.equals(oldDefault);
updateComplianceDefaultSettings(rememberOld, oldValue);
fComplianceStatus= validateCompliance();
validateComplianceStatus();
} else if (PREF_RELEASE.equals(changedKey)) {
setValue(PREF_RELEASE, DISABLED.equals(newValue) ? ENABLED : DISABLED);
updateReleaseOptionStatus();
updateComplianceDefaultSettings(true, null);
fComplianceStatus= validateCompliance();
validateComplianceStatus();
} else if (PREF_SOURCE_COMPATIBILITY.equals(changedKey)) {
updatePreviewFeaturesState();
updateAssertEnumAsIdentifierEnableState();
fComplianceStatus= validateCompliance();
} else if (PREF_CODEGEN_TARGET_PLATFORM.equals(changedKey)) {
if (VERSION_CLDC_1_1.equals(newValue) && !oldValue.equals(newValue)) {
String compliance= getValue(PREF_COMPLIANCE);
String source= getValue(PREF_SOURCE_COMPATIBILITY);
if (!JavaModelUtil.isVersionLessThan(compliance, VERSION_1_5)) {
setValue(PREF_COMPLIANCE, VERSION_1_4);
}
if (!VERSION_1_3.equals(source)) {
setValue(PREF_SOURCE_COMPATIBILITY, VERSION_1_3);
}
}
updateControls();
updateInlineJSREnableState();
updateStoreMethodParamNamesEnableState();
updatePreviewFeaturesState();
updateAssertEnumAsIdentifierEnableState();
fComplianceStatus= validateCompliance();
} else if (PREF_PB_ENUM_AS_IDENTIFIER.equals(changedKey) ||
PREF_PB_ASSERT_AS_IDENTIFIER.equals(changedKey)) {
fComplianceStatus= validateCompliance();
} else if (PREF_ENABLE_PREVIEW.equals(changedKey)) {
fComplianceStatus= validateCompliance();
updatePreviewFeaturesState();
} else if (PREF_PB_REPORT_PREVIEW.equals(changedKey)) {
fComplianceStatus= validateCompliance();
} else {
return;
}
} else {
updateComplianceFollowsEE();
updateControls();
updateComplianceEnableState();
updatePreviewFeaturesState();
updatePreviewControls();
updateAssertEnumAsIdentifierEnableState();
updateInlineJSREnableState();
updateStoreMethodParamNamesEnableState();
fComplianceStatus= validateCompliance();
updateComplianceReleaseSettings();
updateReleaseOptionStatus();
validateComplianceStatus();
}
fContext.statusChanged(fComplianceStatus);
}
public void refreshComplianceSettings() {
if (fOriginalStoredCompliance == null) {
fOriginalStoredCompliance= new String[] { // caution: order depends on IDX_* constants
getOriginalStoredValue(PREF_PB_ASSERT_AS_IDENTIFIER),
getOriginalStoredValue(PREF_PB_ENUM_AS_IDENTIFIER),
getOriginalStoredValue(PREF_SOURCE_COMPATIBILITY),
getOriginalStoredValue(PREF_CODEGEN_TARGET_PLATFORM),
getOriginalStoredValue(PREF_COMPLIANCE),
getOriginalStoredValue(PREF_CODEGEN_INLINE_JSR_BYTECODE),
getOriginalStoredValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR),
getOriginalStoredValue(PREF_RELEASE),
getOriginalStoredValue(PREF_ENABLE_PREVIEW),
getOriginalStoredValue(PREF_PB_REPORT_PREVIEW)
};
} else {
String[] storedCompliance= new String[] {
getOriginalStoredValue(PREF_PB_ASSERT_AS_IDENTIFIER),
getOriginalStoredValue(PREF_PB_ENUM_AS_IDENTIFIER),
getOriginalStoredValue(PREF_SOURCE_COMPATIBILITY),
getOriginalStoredValue(PREF_CODEGEN_TARGET_PLATFORM),
getOriginalStoredValue(PREF_COMPLIANCE),
getOriginalStoredValue(PREF_CODEGEN_INLINE_JSR_BYTECODE),
getOriginalStoredValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR),
getOriginalStoredValue(PREF_RELEASE),
getOriginalStoredValue(PREF_ENABLE_PREVIEW),
getOriginalStoredValue(PREF_PB_REPORT_PREVIEW)
};
if (!Arrays.equals(fOriginalStoredCompliance, storedCompliance)) {
// compliance changed on disk -> override user modifications
fOriginalStoredCompliance= storedCompliance;
setValue(PREF_PB_ASSERT_AS_IDENTIFIER, storedCompliance[IDX_ASSERT_AS_IDENTIFIER]);
setValue(PREF_PB_ENUM_AS_IDENTIFIER, storedCompliance[IDX_ENUM_AS_IDENTIFIER]);
setValue(PREF_SOURCE_COMPATIBILITY, storedCompliance[IDX_SOURCE_COMPATIBILITY]);
setValue(PREF_CODEGEN_TARGET_PLATFORM, storedCompliance[IDX_CODEGEN_TARGET_PLATFORM]);
setValue(PREF_COMPLIANCE, storedCompliance[IDX_COMPLIANCE]);
setValue(PREF_CODEGEN_INLINE_JSR_BYTECODE, storedCompliance[IDX_INLINE_JSR_BYTECODE]);
setValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR, storedCompliance[IDX_METHOD_PARAMETERS_ATTR]);
setValue(PREF_RELEASE, storedCompliance[IDX_RELEASE]);
setValue(PREF_ENABLE_PREVIEW, storedCompliance[IDX_ENABLE_PREVIEW]);
setValue(PREF_PB_REPORT_PREVIEW, storedCompliance[IDX_REPORT_PREVIEW]);
}
updateComplianceFollowsEE();
updateControls();
updateComplianceEnableState();
validateComplianceStatus();
updateInlineJSREnableState();
updateAssertEnumAsIdentifierEnableState();
updatePreviewFeaturesState();
updateStoreMethodParamNamesEnableState();
}
}
@Override
public void performDefaults() {
super.performDefaults();
performReleasePreferenceDefault();
}
private void performReleasePreferenceDefault() {
String defValue= getDefaultValue(PREF_RELEASE);
if (defValue == null) {
defValue= DISABLED;
}
fCompilerReleaseCheck.setSelection(DISABLED.equals(defValue) ? false : true);
setValue(PREF_RELEASE, defValue);
updateReleaseOptionStatus();
}
private void validateComplianceStatus() {
if (fJRE50InfoText != null && !fJRE50InfoText.isDisposed()) {
boolean isVisible= false;
Image image= JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING);
String compliance= getStoredValue(PREF_COMPLIANCE); // get actual value
IVMInstall install= null;
if (fProject != null) { // project specific settings: only test if a 50 JRE is installed
try {
install= JavaRuntime.getVMInstall(JavaCore.create(fProject));
} catch (CoreException e) {
JavaPlugin.log(e);
}
} else {
install= JavaRuntime.getDefaultVMInstall();
}
boolean isJREUnsupportedAndGreater= false;
if (install instanceof IVMInstall2) {
String version= ((IVMInstall2) install).getJavaVersion();
String compilerCompliance= JavaModelUtil.getCompilerCompliance((IVMInstall2) install, compliance);
isJREUnsupportedAndGreater= isJREVersionUnsupportedAndGreater(version, compilerCompliance);
if (isJREUnsupportedAndGreater) {
version= getJREVersionString(version);
}
if (!compilerCompliance.equals(compliance)) { // Discourage using compiler with version other than compliance
String[] args= { getVersionLabel(compliance), getVersionLabel(compilerCompliance) };
if (isJREUnsupportedAndGreater) {
args[1]= getVersionLabel(version);
}
if (JavaModelUtil.is9OrHigher(compilerCompliance)) {
if (!JavaModelUtil.is1d6OrHigher(compliance) || !fCompilerReleaseCheck.getSelection()) {
if (fProject == null) {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info, args));
} else {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info_project, args));
}
} else {
if (JavaModelUtil.is10OrHigher(compilerCompliance) && !JavaModelUtil.is12OrHigher(compilerCompliance)) {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_backwardcompatibility_warning, args));
}
else {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_backwardcompatibility_info, args));
image= JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_INFO); }
}
} else {
if (fProject == null) {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info, args));
} else {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info_project, args));
}
}
isVisible= true;
} else {
if (isJREUnsupportedAndGreater) {
String[] args= { getVersionLabel(compilerCompliance), getVersionLabel(version) };
if (fCompilerReleaseCheck.getSelection()) {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_backwardcompatibility_info, args));
image= JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_INFO);
} else {
if (fProject == null) {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info, args));
} else {
fJRE50InfoText.setText(Messages.format(PreferencesMessages.ComplianceConfigurationBlock_jrecompliance_info_project, args));
}
}
isVisible= true;
}
}
}
//TODO: Comment once Java SE 17 has been shipped:
// String selectedCompliance= getValue(PREF_COMPLIANCE);
// if (VERSION_17.equals(selectedCompliance)) {
// fJRE50InfoText.setText(
// "This is an implementation of an early-draft specification developed under the Java Community Process (JCP) and is made available for testing and evaluation purposes only. The code is not compatible with any specification of the JCP."); //$NON-NLS-1$
// isVisible= true;
// }
fJRE50InfoText.setVisible(isVisible);
fJRE50InfoImage.setImage(isVisible ? image : null);
fJRE50InfoImage.getParent().layout();
}
}
private void updateReleaseOptionStatus() {
if (fCompilerReleaseCheck != null && !fCompilerReleaseCheck.isDisposed()) {
String compliance= getStoredValue(PREF_COMPLIANCE); // get actual value
IVMInstall install= null;
if (fProject != null) { // project specific settings: only test if a 50 JRE is installed
try {
install= JavaRuntime.getVMInstall(JavaCore.create(fProject));
} catch (CoreException e) {
JavaPlugin.log(e);
}
} else {
install= JavaRuntime.getDefaultVMInstall();
}
if (install instanceof IVMInstall2) {
String compilerCompliance= JavaModelUtil.getCompilerCompliance((IVMInstall2) install, compliance);
String version= ((IVMInstall2) install).getJavaVersion();
boolean isJREUnsupportedAndGreater= isJREVersionUnsupportedAndGreater(version, compilerCompliance);
if (!compilerCompliance.equals(compliance)) { // Discourage using compiler with version other than compliance
if (JavaModelUtil.is9OrHigher(compilerCompliance)) {
if (!JavaModelUtil.isVersionLessThan(compliance, compilerCompliance)
|| !JavaModelUtil.is1d6OrHigher(compliance)
|| ( JavaModelUtil.is12OrHigher(compilerCompliance))
&& !JavaModelUtil.is1d7OrHigher(compliance)) {
fCompilerReleaseCheck.setEnabled(false);
fCompilerReleaseCheck.setSelection(false);
setValue(PREF_RELEASE, DISABLED);
} else {
if (fProject != null) {
fCompilerReleaseCheck.setEnabled(checkValue(INTR_COMPLIANCE_FOLLOWS_EE, USER_CONF) || checkValue(INTR_COMPLIANCE_FOLLOWS_EE, DISABLED));
} else {
fCompilerReleaseCheck.setEnabled(true);
}
}
updateComplianceEnableSourceTargetState();
} else {
fCompilerReleaseCheck.setEnabled(false);
fCompilerReleaseCheck.setSelection(false);
setValue(PREF_RELEASE, DISABLED);
}
} else if (!JavaModelUtil.is9OrHigher(compilerCompliance)) {
fCompilerReleaseCheck.setEnabled(false);
fCompilerReleaseCheck.setSelection(false);
setValue(PREF_RELEASE, JavaCore.DISABLED);
} else {
if (fProject == null
|| (isJREUnsupportedAndGreater && JavaModelUtil.is1d6OrHigher(compliance))
|| JavaModelUtil.is9OrHigher(compliance)) {
fCompilerReleaseCheck.setEnabled(true);
}
updateComplianceEnableSourceTargetState();
}
}
}
}
private boolean isJREVersionUnsupportedAndGreater(String version, String compilerCompliance) {
boolean isJREUnsupportedAndGreater= false;
String versionStr= version;
if (!JavaCore.isSupportedJavaVersion(versionStr)) {
try {
versionStr= getJREVersionString(versionStr);
int jreVersion= Integer.parseInt(versionStr);
int supportedVersion= Integer.parseInt(compilerCompliance);
if (jreVersion > supportedVersion) {
isJREUnsupportedAndGreater= true;
}
} catch (NumberFormatException e) {
//do nothing
}
}
return isJREUnsupportedAndGreater;
}
private String getJREVersionString(String version) {
String newVersion= version;
int index= newVersion.indexOf('.');
if (index != -1) {
newVersion= newVersion.substring(0, index);
} else {
index= newVersion.indexOf('-');
if (index != -1)
newVersion= newVersion.substring(0, index);
}
return newVersion;
}
private String getVersionLabel(String version) {
return BasicElementLabels.getVersionName(version);
}
private IStatus validateCompliance() {
StatusInfo status= new StatusInfo();
String compliance= getValue(PREF_COMPLIANCE);
String source= getValue(PREF_SOURCE_COMPATIBILITY);
String target= getValue(PREF_CODEGEN_TARGET_PLATFORM);
if (ComplianceConfigurationBlock.VERSION_JSR14.equals(target)) {
target= source;
}
// compliance must not be smaller than source or target
if (JavaModelUtil.isVersionLessThan(compliance, source)) {
status.setError(PreferencesMessages.ComplianceConfigurationBlock_src_greater_compliance);
return status;
}
if (JavaModelUtil.isVersionLessThan(compliance, target)) {
status.setError(PreferencesMessages.ComplianceConfigurationBlock_classfile_greater_compliance);
return status;
}
if (VERSION_CLDC_1_1.equals(target)) {
if (!VERSION_1_3.equals(source) || !JavaModelUtil.isVersionLessThan(compliance, VERSION_1_5)) {
status.setError(PreferencesMessages.ComplianceConfigurationBlock_cldc11_requires_source13_compliance_se14);
return status;
}
}
// target must not be smaller than source
if (!VERSION_1_3.equals(source) && JavaModelUtil.isVersionLessThan(target, source)) {
status.setError(PreferencesMessages.ComplianceConfigurationBlock_classfile_greater_source);
return status;
}
return status;
}
@Override
public void useProjectSpecificSettings(boolean enable) {
super.useProjectSpecificSettings(enable);
if (!enable) {
initializeReleaseCheckBox(!enable);
}
updateReleaseOptionStatus();
validateComplianceStatus();
}
private void updateComplianceFollowsEE() {
if (fProject != null) {
String complianceFollowsEE= DISABLED;
IExecutionEnvironment ee= getEE();
String label;
if (ee != null) {
complianceFollowsEE= getComplianceFollowsEE(ee);
label= Messages.format(PreferencesMessages.ComplianceConfigurationBlock_compliance_follows_EE_with_EE_label, ee.getId());
} else {
label= PreferencesMessages.ComplianceConfigurationBlock_compliance_follows_EE_label;
}
Link checkBoxLink= getCheckBoxLink(INTR_COMPLIANCE_FOLLOWS_EE);
if (checkBoxLink != null) {
checkBoxLink.setText(label);
}
setValue(INTR_COMPLIANCE_FOLLOWS_EE, complianceFollowsEE);
}
}
private void updateComplianceEnableState() {
boolean enableComplianceControls= true;
if (fProject != null) {
boolean hasProjectSpecificOptions= hasProjectSpecificOptions(fProject);
String complianceFollowsEE= getValue(INTR_COMPLIANCE_FOLLOWS_EE);
updateCheckBox(getCheckBox(INTR_COMPLIANCE_FOLLOWS_EE));
boolean enableComplianceFollowsEE= hasProjectSpecificOptions && ! DISABLED.equals(complianceFollowsEE); // is default or user
updateControlsEnableState(fComplianceFollowsEEControls, enableComplianceFollowsEE);
enableComplianceControls= hasProjectSpecificOptions && ! DEFAULT_CONF.equals(complianceFollowsEE); // is disabled or user
updateControlsEnableState(fComplianceControls, enableComplianceControls);
}
boolean enableComplianceChildren= enableComplianceControls && checkValue(INTR_DEFAULT_COMPLIANCE, USER_CONF);
updateControlsEnableState(fComplianceChildControls, enableComplianceChildren);
updateReleaseOptionStatus();
}
private void updateComplianceEnableSourceTargetState() {
boolean enableComplianceControls= true;
if (fProject != null) {
boolean hasProjectSpecificOptions= hasProjectSpecificOptions(fProject);
String complianceFollowsEE= getValue(INTR_COMPLIANCE_FOLLOWS_EE);
enableComplianceControls= hasProjectSpecificOptions && !DEFAULT_CONF.equals(complianceFollowsEE); // is disabled or user
}
boolean enableBasedOnRelease= !fCompilerReleaseCheck.getSelection() || !JavaModelUtil.is1d6OrHigher(getValue(PREF_COMPLIANCE));
boolean enableComplianceChildren= enableComplianceControls && checkValue(INTR_DEFAULT_COMPLIANCE, USER_CONF) && enableBasedOnRelease;
for (int i= fComplianceChildControls.size() - 1; i >= 0; i--) {
Control curr= fComplianceChildControls.get(i);
ControlData data= (ControlData) curr.getData();
if (data != null) {
if (PREF_SOURCE_COMPATIBILITY.equals(data.getKey())
|| PREF_CODEGEN_TARGET_PLATFORM.equals(data.getKey())) {
Combo combo= getComboBox(data.getKey());
combo.setEnabled(enableComplianceChildren);
}
}
}
}
private void updateControlsEnableState(List<Control> controls, boolean enable) {
for (int i= controls.size() - 1; i >= 0; i--) {
Control curr= controls.get(i);
if (curr instanceof Composite) {
updateControlsEnableState(Arrays.asList(((Composite)curr).getChildren()), enable);
}
curr.setEnabled(enable);
}
if (controls.contains(fReportPreviewCombo)) {
fReportPreviewCombo.setEnabled(fEnablePreviewCheck.isEnabled() && fEnablePreviewCheck.getSelection());
}
}
private void updatePreviewFeaturesState() {
if (checkValue(INTR_DEFAULT_COMPLIANCE, USER_CONF)) {
String compatibility= getValue(PREF_SOURCE_COMPATIBILITY);
boolean isLessThanLatest= JavaModelUtil.isVersionLessThan(compatibility, VERSION_LATEST);
updateRememberedComplianceOption(PREF_ENABLE_PREVIEW, IDX_ENABLE_PREVIEW, !isLessThanLatest, null);
updateRememberedComplianceOption(PREF_PB_REPORT_PREVIEW, IDX_REPORT_PREVIEW, fEnablePreviewCheck.isEnabled() && fEnablePreviewCheck.getSelection(), WARNING);
}
}
private void updatePreviewControls() {
String compliance= getValue(PREF_COMPLIANCE);
if (JavaCore.compareJavaVersions(compliance, VERSION_LATEST) < 0) {
fEnablePreviewCheck.setSelection(false);
fReportPreviewCombo.select(0);
}
}
private void updateAssertEnumAsIdentifierEnableState() {
if (checkValue(INTR_DEFAULT_COMPLIANCE, USER_CONF)) {
String compatibility= getValue(PREF_SOURCE_COMPATIBILITY);
boolean isLessThan14= VERSION_1_3.equals(compatibility);
updateRememberedComplianceOption(PREF_PB_ASSERT_AS_IDENTIFIER, IDX_ASSERT_AS_IDENTIFIER, isLessThan14, ERROR);
boolean isLessThan15= isLessThan14 || VERSION_1_4.equals(compatibility);
updateRememberedComplianceOption(PREF_PB_ENUM_AS_IDENTIFIER, IDX_ENUM_AS_IDENTIFIER, isLessThan15, ERROR);
}
}
private void updateRememberedComplianceOption(Key prefKey, int idx, boolean enabled, String defaultComboValue) {
if (prefKey.getName().equals(PREF_ENABLE_PREVIEW.getName())) {
Button checkBox= getCheckBox(prefKey);
boolean wasCheckBoxEnabled= checkBox.isEnabled();
checkBox.setEnabled(enabled);
if (enabled) {
if (!wasCheckBoxEnabled) {
String val= fRememberedUserCompliance[idx];
if (ENABLED.equals(val)) {
setValue(PREF_ENABLE_PREVIEW, val);
updateCheckBox(checkBox);
}
}
} else {
String val= getValue(PREF_ENABLE_PREVIEW);
if (wasCheckBoxEnabled) {
fRememberedUserCompliance[idx]= val;
}
if (ENABLED.equals(val)) {
setValue(PREF_ENABLE_PREVIEW, DISABLED);
updateCheckBox(checkBox);
}
}
} else {
Combo combo= getComboBox(prefKey);
combo.setEnabled(enabled);
if (!enabled) {
String val= getValue(prefKey);
if (!defaultComboValue.equals(val)) {
setValue(prefKey, defaultComboValue);
updateCombo(combo);
fRememberedUserCompliance[idx]= val;
}
} else {
String val= fRememberedUserCompliance[idx];
if (!defaultComboValue.equals(val)) {
setValue(prefKey, val);
updateCombo(combo);
}
}
}
}
private void updateInlineJSREnableState() {
String target= getValue(PREF_CODEGEN_TARGET_PLATFORM);
boolean enabled= JavaModelUtil.isVersionLessThan(target, VERSION_1_5);
Button checkBox= getCheckBox(PREF_CODEGEN_INLINE_JSR_BYTECODE);
boolean wasCheckBoxEnabled= checkBox.isEnabled();
checkBox.setEnabled(enabled);
if (!enabled) {
String val= getValue(PREF_CODEGEN_INLINE_JSR_BYTECODE);
if (wasCheckBoxEnabled)
fRememberedUserCompliance[IDX_INLINE_JSR_BYTECODE]= val;
if (!ENABLED.equals(val)) {
setValue(PREF_CODEGEN_INLINE_JSR_BYTECODE, ENABLED);
updateCheckBox(checkBox);
}
} else {
if (!wasCheckBoxEnabled) {
String val= fRememberedUserCompliance[IDX_INLINE_JSR_BYTECODE];
if (!ENABLED.equals(val)) {
setValue(PREF_CODEGEN_INLINE_JSR_BYTECODE, val);
updateCheckBox(checkBox);
}
}
}
}
private void updateStoreMethodParamNamesEnableState() {
String target= getValue(PREF_CODEGEN_TARGET_PLATFORM);
boolean enabled= JavaModelUtil.is1d8OrHigher(target);
Button checkBox= getCheckBox(PREF_CODEGEN_METHOD_PARAMETERS_ATTR);
boolean wasCheckBoxEnabled= checkBox.isEnabled();
checkBox.setEnabled(enabled);
if (enabled) {
if (!wasCheckBoxEnabled) {
String val= fRememberedUserCompliance[IDX_METHOD_PARAMETERS_ATTR];
if (GENERATE.equals(val)) {
setValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR, val);
updateCheckBox(checkBox);
}
}
} else {
String val= getValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR);
if (wasCheckBoxEnabled)
fRememberedUserCompliance[IDX_METHOD_PARAMETERS_ATTR]= val;
if (GENERATE.equals(val)) {
setValue(PREF_CODEGEN_METHOD_PARAMETERS_ATTR, DO_NOT_GENERATE);
updateCheckBox(checkBox);
}
}
}
/**
* Sets the default compliance values derived from the chosen level or restores the user
* compliance settings.
*
* @param rememberOld if <code>true</code>, the current compliance settings are remembered as
* user settings. If <code>false</code>, overwrite the current settings.
* @param oldComplianceLevel the previous compliance level
*/
private void updateComplianceDefaultSettings(boolean rememberOld, String oldComplianceLevel) {
String enablePreview, reportPreview, assertAsId, enumAsId, source, target;
boolean isDefault= checkValue(INTR_DEFAULT_COMPLIANCE, DEFAULT_CONF);
boolean isFollowEE= checkValue(INTR_COMPLIANCE_FOLLOWS_EE, DEFAULT_CONF);
String complianceLevel= getValue(PREF_COMPLIANCE);
boolean isRelease= checkValue(PREF_RELEASE, JavaCore.ENABLED) && JavaModelUtil.is1d6OrHigher(complianceLevel) && !isDefault;
if (isDefault || isFollowEE || isRelease) {
if (rememberOld) {
if (oldComplianceLevel == null) {
oldComplianceLevel= complianceLevel;
}
fRememberedUserCompliance[IDX_ENABLE_PREVIEW]= getValue(PREF_ENABLE_PREVIEW);
fRememberedUserCompliance[IDX_REPORT_PREVIEW]= getValue(PREF_PB_REPORT_PREVIEW);
fRememberedUserCompliance[IDX_ASSERT_AS_IDENTIFIER]= getValue(PREF_PB_ASSERT_AS_IDENTIFIER);
fRememberedUserCompliance[IDX_ENUM_AS_IDENTIFIER]= getValue(PREF_PB_ENUM_AS_IDENTIFIER);
fRememberedUserCompliance[IDX_SOURCE_COMPATIBILITY]= getValue(PREF_SOURCE_COMPATIBILITY);
fRememberedUserCompliance[IDX_CODEGEN_TARGET_PLATFORM]= getValue(PREF_CODEGEN_TARGET_PLATFORM);
fRememberedUserCompliance[IDX_RELEASE]= getValue(PREF_RELEASE);
fRememberedUserCompliance[IDX_COMPLIANCE]= oldComplianceLevel;
}
if (isFollowEE) {
IExecutionEnvironment ee= getEE();
Map<String, String> eeOptions= BuildPathSupport.getEEOptions(ee);
if (eeOptions == null)
return;
enablePreview= eeOptions.get(PREF_ENABLE_PREVIEW.getName());
reportPreview= eeOptions.get(PREF_PB_REPORT_PREVIEW.getName());
assertAsId= eeOptions.get(PREF_PB_ASSERT_AS_IDENTIFIER.getName());
enumAsId= eeOptions.get(PREF_PB_ENUM_AS_IDENTIFIER.getName());
source= eeOptions.get(PREF_SOURCE_COMPATIBILITY.getName());
target= eeOptions.get(PREF_CODEGEN_TARGET_PLATFORM.getName());
setValue(PREF_COMPLIANCE, eeOptions.get(PREF_COMPLIANCE.getName()));
String inlineJSR= eeOptions.get(PREF_CODEGEN_INLINE_JSR_BYTECODE.getName());
if (inlineJSR != null) {
setValue(PREF_CODEGEN_INLINE_JSR_BYTECODE, inlineJSR);
}
String release= eeOptions.get(PREF_RELEASE.getName());
if (release == null) {
setValue(PREF_RELEASE, DISABLED);
fCompilerReleaseCheck.setSelection(false);
}
} else if (isRelease) {
enablePreview= getValue(PREF_ENABLE_PREVIEW);
reportPreview= getValue(PREF_PB_REPORT_PREVIEW);
source= getValue(PREF_COMPLIANCE);
target= getValue(PREF_COMPLIANCE);
assertAsId= getValue(PREF_PB_ASSERT_AS_IDENTIFIER);
enumAsId= getValue(PREF_PB_ENUM_AS_IDENTIFIER);
} else {
HashMap<String, String> options= new HashMap<>();
JavaModelUtil.setComplianceOptions(options, complianceLevel);
if (complianceLevel.equals(options.get(JavaCore.COMPILER_COMPLIANCE))) {
enablePreview= options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES);
reportPreview= options.get(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES);
source= options.get(JavaCore.COMPILER_SOURCE);
target= options.get(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM);
assertAsId= options.get(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER);
enumAsId= options.get(JavaCore.COMPILER_PB_ENUM_IDENTIFIER);
} else {
enablePreview= DISABLED;
reportPreview= WARNING;
assertAsId= IGNORE;
enumAsId= IGNORE;
source= VERSION_1_3;
target= VERSION_1_1;
}
}
} else {
if (rememberOld && complianceLevel.equals(fRememberedUserCompliance[IDX_COMPLIANCE])) {
enablePreview= fRememberedUserCompliance[IDX_ENABLE_PREVIEW];
reportPreview= fRememberedUserCompliance[IDX_REPORT_PREVIEW];
assertAsId= fRememberedUserCompliance[IDX_ASSERT_AS_IDENTIFIER];
enumAsId= fRememberedUserCompliance[IDX_ENUM_AS_IDENTIFIER];
source= fRememberedUserCompliance[IDX_SOURCE_COMPATIBILITY];
target= fRememberedUserCompliance[IDX_CODEGEN_TARGET_PLATFORM];
} else {
updateInlineJSREnableState();
updatePreviewFeaturesState();
updateAssertEnumAsIdentifierEnableState();
updateStoreMethodParamNamesEnableState();
return;
}
}
if (enablePreview == null) {
enablePreview= DISABLED;
}
if (reportPreview == null) {
reportPreview= WARNING;
}
setValue(PREF_ENABLE_PREVIEW, enablePreview);
setValue(PREF_PB_REPORT_PREVIEW, reportPreview);
setValue(PREF_PB_ASSERT_AS_IDENTIFIER, assertAsId);
setValue(PREF_PB_ENUM_AS_IDENTIFIER, enumAsId);
setValue(PREF_SOURCE_COMPATIBILITY, source);
setValue(PREF_CODEGEN_TARGET_PLATFORM, target);
updateControls();
updateInlineJSREnableState();
updatePreviewFeaturesState();
updateAssertEnumAsIdentifierEnableState();
updateStoreMethodParamNamesEnableState();
}
private void updateComplianceReleaseSettings() {
String compliance= getValue(PREF_COMPLIANCE);
boolean isRelease= checkValue(PREF_RELEASE, JavaCore.ENABLED) && JavaModelUtil.is1d6OrHigher(compliance);
if (isRelease) {
setValue(PREF_SOURCE_COMPATIBILITY, compliance);
setValue(PREF_CODEGEN_TARGET_PLATFORM, compliance);
}
}
/**
* Evaluate if the current compliance setting correspond to a default setting.
*
* @return {@link #DEFAULT_CONF} or {@link #USER_CONF}
*/
private String getCurrentCompliance() {
String complianceLevel= getValue(PREF_COMPLIANCE);
HashMap<String, String> defaultOptions= new HashMap<>();
JavaModelUtil.setComplianceOptions(defaultOptions, complianceLevel);
boolean isDefault= complianceLevel.equals(defaultOptions.get(JavaCore.COMPILER_COMPLIANCE))
&& getValue(PREF_SOURCE_COMPATIBILITY).equals(defaultOptions.get(JavaCore.COMPILER_SOURCE))
&& getValue(PREF_CODEGEN_TARGET_PLATFORM).equals(defaultOptions.get(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM))
&& getValue(PREF_PB_ASSERT_AS_IDENTIFIER).equals(defaultOptions.get(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER))
&& getValue(PREF_PB_ENUM_AS_IDENTIFIER).equals(defaultOptions.get(JavaCore.COMPILER_PB_ENUM_IDENTIFIER));
if (JavaCore.compareJavaVersions(complianceLevel, JavaCore.VERSION_10) > 0) {
isDefault= isDefault
&& getValue(PREF_ENABLE_PREVIEW).equals(defaultOptions.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES))
&& getValue(PREF_PB_REPORT_PREVIEW).equals(defaultOptions.get(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES));
}
return isDefault ? DEFAULT_CONF : USER_CONF;
}
private IExecutionEnvironment getEE() {
if (fProject == null)
return null;
try {
for (IClasspathEntry entry : JavaCore.create(fProject).getRawClasspath()) {
if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
String eeId= JavaRuntime.getExecutionEnvironmentId(entry.getPath());
if (eeId != null) {
return JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(eeId);
}
}
}
} catch (CoreException e) {
JavaPlugin.log(e);
}
return null;
}
/**
* Evaluate if the builds path contains an execution environment and the current compliance
* settings follow the EE options.
*
* @param ee the EE, or <code>null</code> if none available
* @return {@link #DEFAULT_CONF} if the compliance follows the EE, or {@link #USER_CONF} if the
* settings differ, or {@link #DISABLED} if there's no EE at all
*/
private String getComplianceFollowsEE(IExecutionEnvironment ee) {
Map<String, String> options= BuildPathSupport.getEEOptions(ee);
if (options == null)
return DISABLED;
String complianceOption= options.get(JavaCore.COMPILER_COMPLIANCE);
if (JavaCore.compareJavaVersions(complianceOption, JavaCore.VERSION_10) > 0) {
return checkDefaults(PREFS_COMPLIANCE_11_OR_HIGHER, options);
} else {
return checkDefaults(PREFS_COMPLIANCE, options);
}
}
private String checkDefaults(Key[] keys, Map<String, String> options) {
for (Key key : keys) {
Object option= options.get(key.getName());
if (!checkValue(key, (String)option))
return USER_CONF;
}
return DEFAULT_CONF;
}
@Override
protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
String title= PreferencesMessages.ComplianceConfigurationBlock_needsbuild_title;
String message;
if (workspaceSettings) {
message= PreferencesMessages.ComplianceConfigurationBlock_needsfullbuild_message;
} else {
message= PreferencesMessages.ComplianceConfigurationBlock_needsprojectbuild_message;
}
return new String[] { title, message };
}
/**
* Sets the default compiler compliance options based on the current default JRE in the
* workspace.
*
* @since 3.5
*/
private void setDefaultCompilerComplianceValues() {
IVMInstall defaultVMInstall= JavaRuntime.getDefaultVMInstall();
if (defaultVMInstall instanceof IVMInstall2) {
String complianceLevel= JavaModelUtil.getCompilerCompliance((IVMInstall2)defaultVMInstall, JavaCore.VERSION_1_4);
if (isOriginalDefaultCompliance(complianceLevel)) {
Map<String, String> complianceOptions= new HashMap<>();
JavaModelUtil.setComplianceOptions(complianceOptions, complianceLevel);
String releaseVal= complianceOptions.get(PREF_RELEASE.getName());
setDefaultValue(PREF_COMPLIANCE, complianceOptions.get(PREF_COMPLIANCE.getName()));
setDefaultValue(PREF_PB_ASSERT_AS_IDENTIFIER, complianceOptions.get(PREF_PB_ASSERT_AS_IDENTIFIER.getName()));
setDefaultValue(PREF_PB_ENUM_AS_IDENTIFIER, complianceOptions.get(PREF_PB_ENUM_AS_IDENTIFIER.getName()));
setDefaultValue(PREF_SOURCE_COMPATIBILITY, complianceOptions.get(PREF_SOURCE_COMPATIBILITY.getName()));
setDefaultValue(PREF_CODEGEN_TARGET_PLATFORM, complianceOptions.get(PREF_CODEGEN_TARGET_PLATFORM.getName()));
setDefaultValue(PREF_RELEASE, releaseVal != null ? releaseVal : DISABLED);
if (JavaCore.compareJavaVersions(complianceLevel, JavaCore.VERSION_10) > 0) {
setDefaultValue(PREF_ENABLE_PREVIEW, complianceOptions.get(PREF_ENABLE_PREVIEW.getName()));
setDefaultValue(PREF_PB_REPORT_PREVIEW, complianceOptions.get(PREF_PB_REPORT_PREVIEW.getName()));
} else {
setDefaultValue(PREF_ENABLE_PREVIEW, DISABLED);
setDefaultValue(PREF_PB_REPORT_PREVIEW, WARNING);
}
}
}
}
/**
* Tells whether the compliance option is the same as the original default.
* @param complianceLevel the compliance level
*
* @return <code>true</code> if the compliance is the same as the original default
* @since 3.6
*/
private static final boolean isOriginalDefaultCompliance(String complianceLevel) {
Hashtable<String, String> options= JavaCore.getDefaultOptions();
Preferences bundleDefaults= BundleDefaultsScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
boolean isDefault= equals(JavaCore.COMPILER_COMPLIANCE, bundleDefaults, options)
&& equals(JavaCore.COMPILER_SOURCE, bundleDefaults, options)
&& equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, bundleDefaults, options)
&& equals(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, bundleDefaults, options)
&& equals(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, bundleDefaults, options)
&& equals(JavaCore.COMPILER_RELEASE, bundleDefaults, options);
if (JavaCore.compareJavaVersions(complianceLevel, JavaCore.VERSION_10) > 0) {
isDefault= isDefault
&& equals(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, bundleDefaults, options)
&& equals(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, bundleDefaults, options);
}
return isDefault;
}
/**
* Returns whether the option for the given key is the same in the map and the preferences.
*
* @param key the key of option to test
* @param preferences the preferences
* @param map the map
* @return <code>true</code> if the options are the same in both maps
* @since 3.6
*/
private static boolean equals(String key, Preferences preferences, Map<String, String> map) {
String dummy= ""; //$NON-NLS-1$
String defaultValue= preferences.get(key, dummy);
return defaultValue != null && defaultValue != dummy
? map.containsKey(key) && equals(defaultValue, map.get(key))
: !map.containsKey(key);
}
/**
* Returns whether the objects are equal.
*
* @param o1 an object
* @param o2 an object
* @return <code>true</code> if the two objects are equal
* @since 3.6
*/
private static boolean equals(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
}