| /******************************************************************************* |
| * Copyright (c) 2009, 2013 Andrew Gvozdev 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: |
| * Andrew Gvozdev - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.cdt.managedbuilder.internal.language.settings.providers; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.AbstractExecutableExtensionBase; |
| import org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.cdtvariables.CdtVariableException; |
| import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; |
| import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider; |
| import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage; |
| import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; |
| import org.eclipse.cdt.core.settings.model.ICFileDescription; |
| import org.eclipse.cdt.core.settings.model.ICFolderDescription; |
| import org.eclipse.cdt.core.settings.model.ICLanguageSetting; |
| import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; |
| import org.eclipse.cdt.core.settings.model.ICPathEntry; |
| import org.eclipse.cdt.core.settings.model.ICResourceDescription; |
| import org.eclipse.cdt.core.settings.model.ICSettingBase; |
| import org.eclipse.cdt.core.settings.model.ICSettingEntry; |
| import org.eclipse.cdt.core.settings.model.util.CDataUtil; |
| import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.variables.IStringVariableManager; |
| import org.eclipse.core.variables.VariablesPlugin; |
| |
| /** |
| * Implementation of language settings provider for CDT Managed Build System. |
| */ |
| public class MBSLanguageSettingsProvider extends AbstractExecutableExtensionBase |
| implements ILanguageSettingsBroadcastingProvider { |
| @Override |
| public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, |
| String languageId) { |
| if (cfgDescription == null || rc == null) { |
| return null; |
| } |
| |
| IPath projectPath = rc.getProjectRelativePath(); |
| ICLanguageSetting[] languageSettings = null; |
| |
| if (rc instanceof IFile) { |
| ICLanguageSetting ls = cfgDescription.getLanguageSettingForFile(projectPath, true); |
| if (ls != null) { |
| languageSettings = new ICLanguageSetting[] { ls }; |
| } else { |
| return getSettingEntries(cfgDescription, rc.getParent(), languageId); |
| } |
| } else { |
| ICResourceDescription rcDescription = cfgDescription.getResourceDescription(projectPath, false); |
| languageSettings = getLanguageSettings(rcDescription); |
| } |
| |
| // this list is allowed to contain duplicate entries, cannot be LinkedHashSet |
| List<ICLanguageSettingEntry> list = new ArrayList<>(); |
| |
| if (languageSettings != null) { |
| for (ICLanguageSetting langSetting : languageSettings) { |
| if (langSetting != null) { |
| String id = langSetting.getLanguageId(); |
| if (id == languageId || (id != null && id.equals(languageId))) { |
| int kindsBits = langSetting.getSupportedEntryKinds(); |
| for (int kind = 1; kind <= kindsBits; kind <<= 1) { |
| if ((kindsBits & kind) != 0) { |
| List<ICLanguageSettingEntry> additions = langSetting.getSettingEntriesList(kind); |
| for (ICLanguageSettingEntry entry : additions) { |
| if (entry instanceof ICPathEntry) { |
| // have to use getName() rather than getLocation() and not use IPath operations to avoid collapsing ".." |
| String pathStr = ((ICPathEntry) entry).getName(); |
| if (!new Path(pathStr).isAbsolute()) { |
| // We need to add project-rooted entry for relative path as MBS counts it this way in some UI |
| // The relative entry below also should be added for indexer to resolve from source file locations |
| |
| ICdtVariableManager varManager = CCorePlugin.getDefault() |
| .getCdtVariableManager(); |
| try { |
| // Substitute build/environment variables |
| String location = varManager.resolveValue(pathStr, "", null, //$NON-NLS-1$ |
| cfgDescription); |
| if (!new Path(location).isAbsolute()) { |
| IStringVariableManager mngr = VariablesPlugin.getDefault() |
| .getStringVariableManager(); |
| String projectRootedPath = mngr.generateVariableExpression( |
| "workspace_loc", rc.getProject().getName()) + Path.SEPARATOR //$NON-NLS-1$ |
| + pathStr; |
| // clear "RESOLVED" flag |
| int flags = entry.getFlags() & ~(ICSettingEntry.RESOLVED |
| | ICSettingEntry.VALUE_WORKSPACE_PATH); |
| ICLanguageSettingEntry projectRootedEntry = (ICLanguageSettingEntry) CDataUtil |
| .createEntry(kind, projectRootedPath, projectRootedPath, |
| null, flags); |
| if (!list.contains(projectRootedEntry)) { |
| list.add(projectRootedEntry); |
| } |
| } |
| } catch (CdtVariableException e) { |
| // Swallow exceptions but also log them |
| ManagedBuilderCorePlugin.log(e); |
| } |
| |
| } |
| } |
| if (!list.contains(entry)) { |
| list.add(entry); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| return LanguageSettingsStorage.getPooledList(list); |
| } |
| |
| /** |
| * Get language settings for resource description. |
| */ |
| private ICLanguageSetting[] getLanguageSettings(ICResourceDescription rcDescription) { |
| ICLanguageSetting[] array = null; |
| switch (rcDescription.getType()) { |
| case ICSettingBase.SETTING_PROJECT: |
| case ICSettingBase.SETTING_CONFIGURATION: |
| case ICSettingBase.SETTING_FOLDER: |
| ICFolderDescription foDes = (ICFolderDescription) rcDescription; |
| array = foDes.getLanguageSettings(); |
| break; |
| case ICSettingBase.SETTING_FILE: |
| ICFileDescription fiDes = (ICFileDescription) rcDescription; |
| ICLanguageSetting ls = fiDes.getLanguageSetting(); |
| if (ls != null) { |
| array = new ICLanguageSetting[] { ls }; |
| } |
| } |
| if (array == null) { |
| array = new ICLanguageSetting[0]; |
| } |
| return array; |
| } |
| |
| @Override |
| public LanguageSettingsStorage copyStorage() { |
| class PretendStorage extends LanguageSettingsStorage { |
| @Override |
| public boolean isEmpty() { |
| return false; |
| } |
| |
| @Override |
| public LanguageSettingsStorage clone() throws CloneNotSupportedException { |
| return this; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| // Note that this always triggers change event even if nothing changed in MBS |
| return false; |
| } |
| } |
| return new PretendStorage(); |
| } |
| |
| } |