blob: fa832c66d7983302018418e27f5956daf7f2984a [file] [log] [blame]
/*
* Copyright (c) 2013 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.cdt.internal.qt.core;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializableProvider;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.core.resources.IResource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This provider uses persistent cache to store the include paths for different
* Qt installations. A Qt installation is uniquely identified by the path to
* the qmake binary within the installation.
* <p>
* This result is shared among all Build Configurations that use the provider
* with the same value for the QMAKE environment variable.
*/
public class QtIncludePathsProvider extends LanguageSettingsSerializableProvider {
/**
* The provider identifies Qt installations by the absolute path to the qmake binary. The
* include paths relevant to the installations are computed and persisted in {@link QtIncludePaths}.
*/
private final Map<String, QtIncludePaths> qtInstallHeaders = new HashMap<String, QtIncludePaths>();
/**
* The build configuration stores the path to the qmake binary as an environment variable.
*/
private static final String ENVVAR_QMAKE = "QMAKE";
private static final String ELEMENT_QMAKE = "qmake";
@Override
public boolean equals(Object obj) {
if (!(obj instanceof QtIncludePathsProvider))
return super.equals(obj);
/**
* Providers are equal when they have the same cached values.
*/
QtIncludePathsProvider other = (QtIncludePathsProvider) obj;
if (qtInstallHeaders == null)
return other.qtInstallHeaders == null;
return qtInstallHeaders.equals(other.qtInstallHeaders);
}
@Override
public int hashCode() {
return qtInstallHeaders == null ? 0 : qtInstallHeaders.hashCode();
}
@Override
public void loadEntries(Element providerNode) {
super.loadEntries(providerNode);
// Find and load all qmake child nodes. There will be one node for each Qt
// installation that has been used. Qt installations that are no longer valid
// are not loaded. This means they will be removed from the file the next time
// that the language setting providers are serialized.
NodeList children = providerNode.getChildNodes();
for (int i = 0; i < children.getLength(); ++i) {
Node child = children.item(i);
if (ELEMENT_QMAKE.equals(child.getNodeName())) {
QtIncludePaths qtIncludePaths = QtIncludePaths.loadFrom(child);
if (qtIncludePaths != null
&& qtIncludePaths.isValid())
qtInstallHeaders.put(qtIncludePaths.getQMakePath(), qtIncludePaths);
}
}
}
@Override
public void serializeEntries(Element parent) {
// NOTE: This creates its own XML structure where children of the provider node are qmake nodes.
// Within each qmake node is a list of include paths for that installation. Calling the
// base #serializeEntries here would try to write this instance's (empty) list of settings
// to the file.
// Each value is serialized into a new element in the XML document.
Document document = parent instanceof Document ? (Document)parent : parent.getOwnerDocument();
for(QtIncludePaths qtIncludePaths : qtInstallHeaders.values()) {
Element child = document.createElement(ELEMENT_QMAKE);
qtIncludePaths.serialize(child);
parent.appendChild(child);
}
}
/**
* The given build configuration's QMAKE environment variable is used to identify the appropriate
* Qt installation. The language settings are then either returned from the previously persisted
* data or loaded, serialized, and returned.
*/
@Override
public synchronized List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription configDesc, IResource rc, String languageId) {
// Make sure the requested language is in scope for this provider.
if (!getLanguageScope().contains(languageId))
return null;
// The value of the build configuration's QMAKE environment variable is used to select the
// right version of qmake.
IEnvironmentVariable qmake_var = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENVVAR_QMAKE, configDesc, true);
if (qmake_var == null)
return null;
String qmake = qmake_var.getValue();
if (qmake == null)
return null;
// The path to qmake is used as the key into the in-memory cache of header paths.
QtIncludePaths paths = qtInstallHeaders.get(qmake);
if (paths == null) {
paths = new QtIncludePaths(qmake);
qtInstallHeaders.put(qmake, paths);
}
return paths.getSettingEntries(configDesc, null, languageId);
}
}