summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Kaspar2013-11-28 13:58:37 (EST)
committer Doug Schaefer2013-11-28 23:33:42 (EST)
commit026b9325f08f899d0b770b2e0968446599144c74 (patch)
tree93a31b5d0579f71ef479e24868bb1732d73d7056
parentf887c8e671725af7d3f18ed55d65d2235036fa5b (diff)
downloadorg.eclipse.cdt-026b9325f08f899d0b770b2e0968446599144c74.zip
org.eclipse.cdt-026b9325f08f899d0b770b2e0968446599144c74.tar.gz
org.eclipse.cdt-026b9325f08f899d0b770b2e0968446599144c74.tar.bz2
Bug 422797 - API for retrieving QMake information from Qt projectrefs/changes/82/19082/2
API is located at org.eclipse.cdt.qt.core.index package. Entry point is QMakeProjectInfoFactory.getForActiveConfigurationIn method that provides ability to retrieve QMake information (IQMakeInfo interface) for active project configuration of a specified project. Also allows to listen on changes of such information. qmakeEnvProvider extensions allows CDT build-system to provide environment for QMake runs within their build-system. Information is gather by parsing output of: 1) qmake -query 2) qmake -E file.pro // only for QMake version 3.0 Change-Id: Iae569bdbc89dc26d60530596b66b5227f36dfae6 Signed-off-by: David Kaspar <dkaspar@blackberry.com> Reviewed-on: https://git.eclipse.org/r/19082 Reviewed-by: Andrew Eidsness <eclipse@jfront.com> Tested-by: Hudson CI Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com>
-rw-r--r--qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF4
-rw-r--r--qt/org.eclipse.cdt.qt.core/build.properties3
-rw-r--r--qt/org.eclipse.cdt.qt.core/plugin.properties1
-rw-r--r--qt/org.eclipse.cdt.qt.core/plugin.xml2
-rw-r--r--qt/org.eclipse.cdt.qt.core/schema/qmakeEnvProvider.exsd136
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderDescriptor.java146
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderManager.java117
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeInfo.java199
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeParser.java211
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeProjectInfo.java426
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeVersion.java63
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtNature.java13
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java45
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnv.java27
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnvProvider.java49
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeInfo.java92
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfo.java40
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfoListener.java21
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQtVersion.java27
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeEnvInfo.java81
-rw-r--r--qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeProjectInfoFactory.java33
21 files changed, 1730 insertions, 6 deletions
diff --git a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
index 31d4aee..bb85c8e 100644
--- a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
+++ b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF
@@ -7,8 +7,10 @@ Bundle-Activator: org.eclipse.cdt.qt.core.QtPlugin
Bundle-Vendor: Eclipse CDT
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
+ org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
org.eclipse.cdt.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
-Export-Package: org.eclipse.cdt.qt.core
+Export-Package: org.eclipse.cdt.qt.core,
+ org.eclipse.cdt.qt.core.index
diff --git a/qt/org.eclipse.cdt.qt.core/build.properties b/qt/org.eclipse.cdt.qt.core/build.properties
index 09a194a..d8b18e5 100644
--- a/qt/org.eclipse.cdt.qt.core/build.properties
+++ b/qt/org.eclipse.cdt.qt.core/build.properties
@@ -5,4 +5,5 @@ bin.includes = META-INF/,\
plugin.xml,\
templates/,\
about.html
-src.includes = about.html
+src.includes = about.html,\
+ schema/
diff --git a/qt/org.eclipse.cdt.qt.core/plugin.properties b/qt/org.eclipse.cdt.qt.core/plugin.properties
index 0206fd1..9f9360a 100644
--- a/qt/org.eclipse.cdt.qt.core/plugin.properties
+++ b/qt/org.eclipse.cdt.qt.core/plugin.properties
@@ -1,2 +1,3 @@
qtProjectFile.name = Qt Project File
qmlFile.name = QML File
+qmakeEnvProvider.name = QMake Environment Provider
diff --git a/qt/org.eclipse.cdt.qt.core/plugin.xml b/qt/org.eclipse.cdt.qt.core/plugin.xml
index d31e961..eb99e06 100644
--- a/qt/org.eclipse.cdt.qt.core/plugin.xml
+++ b/qt/org.eclipse.cdt.qt.core/plugin.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
+ <extension-point id="qmakeEnvProvider" name="%qmakeEnvProvider.name" schema="schema/qmakeEnvProvider.exsd"/>
+
<extension
point="org.eclipse.cdt.core.templates">
<template
diff --git a/qt/org.eclipse.cdt.qt.core/schema/qmakeEnvProvider.exsd b/qt/org.eclipse.cdt.qt.core/schema/qmakeEnvProvider.exsd
new file mode 100644
index 0000000..2c6dfad
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/schema/qmakeEnvProvider.exsd
@@ -0,0 +1,136 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.cdt.qt.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.cdt.qt.core" id="qmakeEnvProvider" name="QMake Environment Provider"/>
+ </appinfo>
+ <documentation>
+ This extension point allows to provide environment for qmake cmd-line tool execution.
+ </documentation>
+ </annotation>
+
+ <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="qmakeEnvProvider" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+ a fully qualified identifier of the target extension point
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ an optional identifier of the extension instance
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the extension instance
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="qmakeEnvProvider">
+ <complexType>
+ <sequence>
+ <element ref="enablement" minOccurs="0" maxOccurs="1"/>
+ </sequence>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ Implementation of QMake environment provider which is used to determinate environment for running QMake.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.cdt.qt.core.index.IQMakeEnvProvider"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="priority" type="integer" default="0">
+ <annotation>
+ <documentation>
+ Priority of QMake environment provider. Less number means higher priority. Default priority is 0.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ 8.2
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ The following is an example of a qmakeEnvProvider contribution:
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension
+ point=&quot;org.eclipse.cdt.qt.core.qmakeEnvProvider&quot;
+ id=&quot;example&quot;
+ name=&quot;Example QMake Env Provider Extension&quot;&gt;
+ &lt;qmakeEnvProvider
+ class=&quot;com.example.internal.ExampleProvider&quot;&gt;
+ &lt;enablement&gt;
+ &lt;with variable=&quot;projectNatures&quot;&gt;
+ &lt;iterate operator=&quot;or&quot;&gt;
+ &lt;equals value=&quot;com.example.my-nature&quot;/&gt;
+ &lt;/iterate&gt;
+ &lt;/with&gt;
+ &lt;/enablement&gt;
+ &lt;/qmakeEnvProvider&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ The contributed class must implement &lt;code&gt;org.eclipse.cdt.qt.core.index.IQMakeEnvProvider&lt;/code&gt;.
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ 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
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderDescriptor.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderDescriptor.java
new file mode 100644
index 0000000..63f6b4a
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderDescriptor.java
@@ -0,0 +1,146 @@
+/*
+ * 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.index;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.qt.core.QtPlugin;
+import org.eclipse.cdt.qt.core.index.IQMakeEnv;
+import org.eclipse.cdt.qt.core.index.IQMakeEnvProvider;
+import org.eclipse.cdt.qt.core.index.IQMakeEnvProvider.IController;
+import org.eclipse.core.expressions.EvaluationContext;
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.ExpressionConverter;
+import org.eclipse.core.expressions.ExpressionTagNames;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * Represents a IQMakeEnvProvider that is registered via qmakeEnvProvider extension point.
+ */
+public final class QMakeEnvProviderDescriptor implements Comparable<QMakeEnvProviderDescriptor> {
+
+ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+ private static final String ATTR_PRIORITY = "priority"; //$NON-NLS-1$
+ private static final String VAR_PROJECTNATURES = "projectNatures"; //$NON-NLS-1$
+
+ private final IConfigurationElement element;
+ private final String id;
+ private final int priority;
+ private final AtomicReference<Boolean> evaluation = new AtomicReference<Boolean>();
+ private final Expression enablementExpression;
+
+ private IQMakeEnvProvider provider;
+
+ QMakeEnvProviderDescriptor(IConfigurationElement element) {
+ this.element = element;
+
+ id = element.getContributor().getName();
+
+ // parse priority
+ int prio = 0;
+ String priorityString = element.getAttribute(ATTR_PRIORITY);
+ if (priorityString != null) {
+ try {
+ prio = Integer.parseInt(priorityString);
+ } catch (NumberFormatException e) {
+ QtPlugin.log("Invalid priority value of " + id, e); //$NON-NLS-1$
+ }
+ }
+ this.priority = prio;
+
+ // parse enablement expression
+ Expression expr = null;
+ IConfigurationElement[] children = element.getChildren(ExpressionTagNames.ENABLEMENT);
+ switch (children.length) {
+ case 0:
+ evaluation.set(Boolean.TRUE);
+ break;
+ case 1:
+ try {
+ ExpressionConverter parser = ExpressionConverter.getDefault();
+ expr = parser.perform(children[0]);
+ } catch (CoreException e) {
+ QtPlugin.log("Error in enablement expression of " + id, e); //$NON-NLS-1$
+ }
+ break;
+ default:
+ QtPlugin.log("Too many enablement expressions for " + id); //$NON-NLS-1$
+ evaluation.set(Boolean.FALSE);
+ break;
+ }
+ enablementExpression = expr;
+ }
+
+ @Override
+ public int compareTo(QMakeEnvProviderDescriptor that) {
+ if (that == null) {
+ return -1;
+ }
+ return this.priority - that.priority;
+ }
+
+ /**
+ * Used by QMakeEnvProviderManager to ask for creating a IQMakeEnv for a specific IQMakeEnvProvider.IController using the related IQMakeEnvProvider
+ *
+ * @param controller the controller
+ * @return the IQMakeEnv instance; or null if no instance is provided
+ */
+ public IQMakeEnv createEnv(IController controller) {
+ if (! matches(controller)) {
+ return null;
+ }
+ if (provider == null) {
+ synchronized (this) {
+ if (provider == null) {
+ try {
+ provider = (IQMakeEnvProvider) element.createExecutableExtension(ATTR_CLASS);
+ } catch (CoreException e) {
+ QtPlugin.log("Error in class attribute of " + id, e); //$NON-NLS-1$
+ return null;
+ }
+ }
+ }
+ }
+ return provider.createEnv(controller);
+ }
+
+ /**
+ * Checks whether an enablement expression evaluation is true.
+ *
+ * @param controller the controller
+ * @return true if the provider can be used; false otherwise
+ */
+ private boolean matches(IController controller) {
+ Boolean eval = evaluation.get();
+ if (eval != null) {
+ return eval.booleanValue();
+ }
+ if (enablementExpression != null) {
+ ICConfigurationDescription configuration = controller != null ? controller.getConfiguration() : null;
+ IProject project = configuration != null ? configuration.getProjectDescription().getProject() : null;
+ EvaluationContext evalContext = new EvaluationContext(null, project);
+ try {
+ if (project != null) {
+ String[] natures = project.getDescription().getNatureIds();
+ evalContext.addVariable(VAR_PROJECTNATURES, Arrays.asList(natures));
+ }
+ return enablementExpression.evaluate(evalContext) == EvaluationResult.TRUE;
+ } catch (CoreException e) {
+ QtPlugin.log("Error while evaluating enablement expression for " + id, e); //$NON-NLS-1$
+ }
+ }
+ evaluation.set(Boolean.FALSE);
+ return false;
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderManager.java
new file mode 100644
index 0000000..f1758ef
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeEnvProviderManager.java
@@ -0,0 +1,117 @@
+/*
+ * 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.index;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.qt.core.QtPlugin;
+import org.eclipse.cdt.qt.core.index.IQMakeEnv;
+import org.eclipse.cdt.qt.core.index.IQMakeEnvProvider;
+import org.eclipse.cdt.qt.core.index.QMakeEnvInfo;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * Represents a manager of registered qmakeEnvProvider extensions.
+ */
+public final class QMakeEnvProviderManager {
+
+ private static QMakeEnvProviderManager INSTANCE = new QMakeEnvProviderManager();
+
+ private final List<QMakeEnvProviderDescriptor> descriptors;
+
+ public static QMakeEnvProviderManager getInstance() {
+ return INSTANCE;
+ }
+
+ private QMakeEnvProviderManager() {
+ descriptors = loadDescriptors();
+ }
+
+ /**
+ * Returns a list of all registerd qmakeEnvProvider extensions.
+ *
+ * @return the list of extensions
+ */
+ private static List<QMakeEnvProviderDescriptor> loadDescriptors() {
+ List<QMakeEnvProviderDescriptor> descriptors = new ArrayList<QMakeEnvProviderDescriptor>();
+ IConfigurationElement[] elements = Platform.getExtensionRegistry()
+ .getConfigurationElementsFor(QtPlugin.ID, QtPlugin.QMAKE_ENV_PROVIDER_EXT_POINT_NAME);
+ for (IConfigurationElement element : elements) {
+ descriptors.add(new QMakeEnvProviderDescriptor(element));
+ }
+ Collections.sort(descriptors);
+ return descriptors;
+ }
+
+ /**
+ * Called by QMakeProjectInfo to create IQMakeEnv for a specified IController.
+ * It asks each qmakeEnvProvider extensions to provide the instance. If none of them provides, then the default IQMakeEnvProvider is returned.
+ *
+ * @param controller the controller
+ * @return the IQMakeEnv instance for specifying the QMake environment
+ */
+ public IQMakeEnv createEnv(IQMakeEnvProvider.IController controller) {
+ for (QMakeEnvProviderDescriptor descriptor : descriptors) {
+ IQMakeEnv env = descriptor.createEnv(controller);
+ if (env != null) {
+ return env;
+ }
+ }
+ return new ConfigurationQMakeEnv(controller.getConfiguration());
+ }
+
+ /**
+ * Represents a fallback IQMakeEnvProvider that is used for a project that has QtNature
+ * while there is no registered IQMakeEnvProvider that would provide any IQMakeEnv.
+ */
+ private static class ConfigurationQMakeEnv implements IQMakeEnv {
+
+ private static final String PRO_FILE_SUFFIX = ".pro"; //$NON-NLS-1$
+ private static final String ENV_VAR_QMAKE = "QMAKE"; //$NON-NLS-1$
+
+ private final ICConfigurationDescription configuration;
+
+ public ConfigurationQMakeEnv(ICConfigurationDescription configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ /**
+ * Returns QMakeEnvInfo resolved from a project in a generic way.
+ * If exists, the root-level .pro file is resolved as the one that is located directly under the project and has the same name.
+ * If exists, qmake executable is resolved from "QMAKE" environment variable that is stored in the project configuration.
+ *
+ * @return the QMakeEnvInfo instance if the project configuration exists; otherwise null.
+ */
+ @Override
+ public QMakeEnvInfo getQMakeEnvInfo() {
+ if (configuration == null) {
+ return null;
+ }
+ IProject project = configuration.getProjectDescription().getProject();
+ IFile proFile = project != null ? project.getFile(project.getName() + PRO_FILE_SUFFIX) : null;
+
+ IEnvironmentVariable variable = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_VAR_QMAKE, configuration, true);
+ String qmakeFilePath = variable != null ? variable.getValue() : null;
+ return new QMakeEnvInfo(proFile, qmakeFilePath, Collections.<String,String>emptyMap(), Collections.<IFile>emptyList());
+ }
+
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeInfo.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeInfo.java
new file mode 100644
index 0000000..c4f769e
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeInfo.java
@@ -0,0 +1,199 @@
+/*
+ * 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.index;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.qt.core.QtPlugin;
+import org.eclipse.cdt.qt.core.index.IQtVersion;
+import org.eclipse.cdt.qt.core.index.IQMakeInfo;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+
+/**
+ * Holder for QMake information.
+ */
+public final class QMakeInfo implements IQMakeInfo {
+
+ // reg. exp. for parsing output of "qmake -query" command
+ public static final Pattern PATTERN_QUERY_LINE = Pattern.compile("^(\\w+):(.*)$");
+ // reg. exp. for parsing output of "qmake -E file.pro" command (for QMake 3.0 only)
+ public static final Pattern PATTERN_EVAL_LINE = Pattern.compile("^([a-zA-Z0-9_\\.]+)\\s*=\\s*(.*)$");
+
+ /**
+ * Instance that is used to present an invalid IQMakeInfo.
+ */
+ public static final IQMakeInfo INVALID = new QMakeInfo(
+ false, null, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList());
+
+ private final boolean valid;
+ private final IQtVersion qtVersion;
+ private final List<String> involvedQMakeFiles;
+ private final List<String> qtImportPath;
+ private final List<String> qtQmlPath;
+ private final List<String> includePath;
+ private final List<String> defines;
+ private final List<String> sourceFiles;
+ private final List<String> headerFiles;
+ private final List<String> otherFiles;
+
+ private QMakeInfo(boolean valid, IQtVersion qtVersion, List<String> involvedQMakeFiles, List<String> qtImportPath, List<String> qtQmlPath, List<String> includePath, List<String> defines, List<String> sourceFiles, List<String> headerFiles, List<String> otherFiles) {
+ this.valid = valid;
+ this.qtVersion = qtVersion;
+ this.involvedQMakeFiles = Collections.unmodifiableList(involvedQMakeFiles);
+ this.qtImportPath = Collections.unmodifiableList(qtImportPath);
+ this.qtQmlPath = Collections.unmodifiableList(qtQmlPath);
+ this.includePath = Collections.unmodifiableList(includePath);
+ this.defines = Collections.unmodifiableList(defines);
+ this.sourceFiles = Collections.unmodifiableList(sourceFiles);
+ this.headerFiles = Collections.unmodifiableList(headerFiles);
+ this.otherFiles = Collections.unmodifiableList(otherFiles);
+ }
+
+ public static IQMakeInfo create(File projectFile, File qmake, String[] extraEnv) {
+ return create(projectFile.getAbsolutePath(), qmake.getAbsolutePath(), extraEnv);
+ }
+
+ public static IQMakeInfo create(String proPath, String qmakePath, String[] extraEnv) {
+ if (proPath == null || qmakePath == null) {
+ return INVALID;
+ }
+
+ // run "qmake -query"
+ Map<String, String> qmake1 = exec(PATTERN_QUERY_LINE, extraEnv, qmakePath, "-query");
+ if (qmake1 == null)
+ return INVALID;
+
+ // check the qmake version
+ QMakeVersion version = QMakeVersion.create(qmake1.get(QMakeParser.KEY_QMAKE_VERSION));
+
+ // TODO - no support for pre-3.0
+ // for QMake version 3.0 or newer, run "qmake -E file.pro"
+ Map<String, String> qmake2 = version != null && version.getMajor() >= 3 ? exec(PATTERN_EVAL_LINE, extraEnv, qmakePath, "-E", proPath) : Collections.<String,String>emptyMap();
+
+ IQtVersion qtVersion = QMakeVersion.create(qmake1.get(QMakeParser.KEY_QT_VERSION));
+ List<String> qtImportPaths = QMakeParser.singleValue(qmake1, QMakeParser.KEY_QT_INSTALL_IMPORTS);
+ List<String> qtQmlPaths = QMakeParser.singleValue(qmake1, QMakeParser.KEY_QT_INSTALL_QML);
+
+ List<String> involvedQMakeFiles = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_QMAKE_INTERNAL_INCLUDED_FILES);
+ List<String> includePath = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_INCLUDEPATH);
+ List<String> defines = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_DEFINES);
+ List<String> sourceFiles = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_SOURCES);
+ List<String> headerFiles = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_HEADERS);
+ List<String> otherFiles = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_HEADERS);
+ List<String> qmlImportPath = QMakeParser.qmake3DecodeValueList(qmake2, QMakeParser.KEY_QML_IMPORT_PATH);
+
+ // combine qtImportPath and qtQmlPath from both qmake runs
+ List<String> realQtImportPaths = new ArrayList<String>(qtImportPaths);
+ realQtImportPaths.addAll(qmlImportPath);
+ List<String> realQtQmlPaths = new ArrayList<String>(qtQmlPaths);
+ realQtQmlPaths.addAll(qmlImportPath);
+
+ return new QMakeInfo(true, qtVersion, involvedQMakeFiles, realQtImportPaths, realQtQmlPaths, includePath, defines, sourceFiles, headerFiles, otherFiles);
+ }
+
+ @Override
+ public boolean isValid() {
+ return valid;
+ }
+
+ @Override
+ public IQtVersion getQtVersion() {
+ return qtVersion;
+ }
+
+ @Override
+ public List<String> getInvolvedQMakeFiles() {
+ return involvedQMakeFiles;
+ }
+
+ @Override
+ public List<String> getQtImportPath() {
+ return qtImportPath;
+ }
+
+ @Override
+ public List<String> getQtQmlPath() {
+ return qtQmlPath;
+ }
+
+ @Override
+ public List<String> getIncludePath() {
+ return includePath;
+ }
+
+ @Override
+ public List<String> getDefines() {
+ return defines;
+ }
+
+ @Override
+ public List<String> getSourceFiles() {
+ return sourceFiles;
+ }
+
+ @Override
+ public List<String> getHeaderFiles() {
+ return headerFiles;
+ }
+
+ @Override
+ public List<String> getOtherFiles() {
+ return otherFiles;
+ }
+
+ /**
+ * Executes a command and parses its output into a map.
+ *
+ * @param regex the reg. exp. used for parsing the output
+ * @param extraEnv the extra environment for command
+ * @param cmd the command line
+ * @return the map of resolved key-value pairs
+ */
+ @SuppressWarnings("resource")
+ private static Map<String, String> exec(Pattern regex, String[] extraEnv, String...command) {
+ if (command.length < 1 || ! new File(command[0]).exists()) {
+ QtPlugin.log("qmake: cannot run command: " + (command.length > 0 ? command[0] : ""));
+ return null;
+ }
+ BufferedReader reader = null;
+ Process process = null;
+ try {
+ if (extraEnv != null && extraEnv.length > 0) {
+ process = ProcessFactory.getFactory().exec(command, extraEnv);
+ } else {
+ process = ProcessFactory.getFactory().exec(command);
+ }
+ reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ return QMakeParser.parse(regex, reader);
+ } catch(IOException e) {
+ QtPlugin.log(e);
+ return null;
+ } finally {
+ if (reader != null)
+ try {
+ reader.close();
+ } catch(IOException e) {
+ /* ignore */
+ }
+ if (process != null) {
+ process.destroy();
+ }
+ }
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeParser.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeParser.java
new file mode 100644
index 0000000..c412ec9
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeParser.java
@@ -0,0 +1,211 @@
+/*
+ * 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.index;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.qt.core.QtPlugin;
+
+/**
+ * Provides a parser for QMake output.
+ */
+public final class QMakeParser {
+
+ public static final String KEY_QMAKE_VERSION = "QMAKE_VERSION";
+ public static final String KEY_QT_VERSION = "QT_VERSION";
+ public static final String KEY_QT_INSTALL_IMPORTS = "QT_INSTALL_IMPORTS";
+ public static final String KEY_QT_INSTALL_QML = "QT_INSTALL_QML";
+ public static final String KEY_QMAKE_INTERNAL_INCLUDED_FILES = "QMAKE_INTERNAL_INCLUDED_FILES";
+ public static final String KEY_SOURCES = "SOURCES";
+ public static final String KEY_HEADERS = "HEADERS";
+ public static final String KEY_INCLUDEPATH = "INCLUDEPATH";
+ public static final String KEY_DEFINES = "DEFINES";
+ public static final String KEY_QML_IMPORT_PATH = "QML_IMPORT_PATH";
+
+ /**
+ * Parses QMake output via a specified reg. exp.
+ *
+ * @param regex the reg. exp.
+ * @param reader the QMake output
+ * @return the map of parsed key-value pairs
+ * @throws IOException when io error happens
+ */
+ public static Map<String, String> parse(Pattern regex, BufferedReader reader) throws IOException {
+ Map<String, String> result = new LinkedHashMap<String, String>();
+
+ String line;
+ while((line = reader.readLine()) != null) {
+ Matcher m = regex.matcher(line);
+ if (!m.matches() || m.groupCount() != 2) {
+ QtPlugin.log("qmake: cannot decode query line '" + line + '\'');
+ } else {
+ String key = m.group(1);
+ String value = m.group(2);
+ String oldValue = result.put(key, value);
+ if (oldValue != null)
+ QtPlugin.log("qmake: duplicate keys in query info '" + line + "' was '" + oldValue + '\'');
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a list with 0-1 values for a specific QMake variable.
+ *
+ * @param map the map
+ * @param key the QMake variable
+ * @return the list of values
+ */
+ public static List<String> singleValue(Map<String, String> map, String key) {
+ String value = map.get(key);
+ return value == null ? Collections.<String>emptyList() : Collections.singletonList(value);
+ }
+
+ /**
+ * Returns a list of values for a specific QMake variable that is decoded as a list of values.
+ *
+ * @param map the map
+ * @param key the QMake variable
+ * @return the list of values
+ */
+ public static List<String> qmake3DecodeValueList(Map<String, String> map, String key) {
+ String value = map.get(key);
+ if (value == null) {
+ return Collections.emptyList();
+ }
+
+ List<String> result = new ArrayList<String>();
+ for (String item : qmake3SplitValueList(value)) {
+ result.add(qmake3DecodeValue(item));
+ }
+ return result;
+ }
+
+ /**
+ * Decodes a specified QMake variable value.
+ *
+ * @param value the value
+ * @return the decoded value
+ */
+ public static String qmake3DecodeValue(String value) {
+ int length = value.length();
+ if (length >= 2 && value.charAt(0) == '"' && value.charAt(length - 1) == '"') {
+ value = value.substring(1, length - 1);
+ length = value.length();
+ }
+ StringBuilder sb = new StringBuilder(length);
+ for (int i = 0; i < length; i ++) {
+ char c = value.charAt(i);
+ if (c == '\\') {
+ ++ i;
+ if (i < length) {
+ char next = value.charAt(i);
+ switch (next) {
+ case 'r':
+ sb.append('\r');
+ break;
+ case 'n':
+ sb.append ('\n');
+ break;
+ case 't':
+ sb.append ('\t');
+ break;
+ case '\\':
+ case '\'':
+ case '"':
+ sb.append (next);
+ break;
+ case 'x':
+ i += 2;
+ if (i < length) {
+ char first = value.charAt(i - 1);
+ char second = value.charAt(i);
+ if (first >= '0' && first <= '9' && second >= '0' && second <= '9') {
+ sb.append ((char) ((first - '0') * 16 + (second - '0')));
+ }
+ }
+ }
+ }
+ } else {
+ sb.append (c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Splits a specified QMake variable value into a list of values.
+ *
+ * @param value the value
+ * @return the list of values
+ */
+ private static List<String> qmake3SplitValueList(String value) {
+ List<String> result = new ArrayList<String>();
+ StringBuilder sb = new StringBuilder();
+ char quote = 0;
+ boolean hadWord = false;
+ final int length = value.length();
+ for (int i = 0; i < length; i ++) {
+ char c = value.charAt(i);
+ if (quote == c) {
+ quote = 0;
+ hadWord = true;
+ sb.append(c);
+ continue;
+ }
+
+ switch (c) {
+ case '"':
+ case '\'':
+ quote = c;
+ hadWord = true;
+ break;
+ case ' ':
+ case '\t':
+ if (quote == 0) {
+ if (hadWord) {
+ result.add(sb.toString());
+ sb.delete(0, sb.length());
+ hadWord = false;
+ }
+ continue;
+ }
+ break;
+ case '\\':
+ if (i + 1 < length) {
+ char nextChar = value.charAt(i + 1);
+ if (nextChar == '\'' || nextChar == '"' || nextChar == '\\') {
+ sb.append(c);
+ c = nextChar;
+ ++ i;
+ }
+ }
+ //$FALL-THROUGH$
+ default:
+ hadWord = true;
+ break;
+ }
+ sb.append (c);
+ }
+
+ if (hadWord) {
+ result.add(sb.toString());
+ }
+
+ return Collections.unmodifiableList(result);
+ }
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeProjectInfo.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeProjectInfo.java
new file mode 100644
index 0000000..331e662
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeProjectInfo.java
@@ -0,0 +1,426 @@
+/*
+ * 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.index;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICDescriptionDelta;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener;
+import org.eclipse.cdt.qt.core.QtNature;
+import org.eclipse.cdt.qt.core.index.IQMakeEnv;
+import org.eclipse.cdt.qt.core.index.IQMakeEnvProvider;
+import org.eclipse.cdt.qt.core.index.IQMakeProjectInfo;
+import org.eclipse.cdt.qt.core.index.IQMakeProjectInfoListener;
+import org.eclipse.cdt.qt.core.index.QMakeEnvInfo;
+import org.eclipse.cdt.qt.core.index.IQMakeInfo;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * Represents a QMake project information that is based on an activate project configuration of a specified related IProject.
+ * Allows to resolve actual information and listen its change.
+ * Manages life-cycle of all QMakeProjectInfo instances.
+ */
+public final class QMakeProjectInfo implements IQMakeProjectInfo, ICProjectDescriptionListener {
+
+ private static final RCListener LISTENER = new RCListener();
+ // sync object for CACHE field
+ private static final Object SYNC = new Object();
+ // a map of all QMakeProjectInfo instances
+ private static final Map<IProject,QMakeProjectInfo> CACHE = new HashMap<IProject,QMakeProjectInfo>();
+
+ // called by QtPlugin activator to setup this class
+ public static final void start() {
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(LISTENER, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE);
+ }
+
+ // called by QtPlugin activator to clean up this class
+ public static final void stop() {
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(LISTENER);
+ synchronized (SYNC) {
+ while (true) {
+ Iterator<IProject> iterator = CACHE.keySet().iterator();
+ if (!iterator.hasNext()) {
+ break;
+ }
+ removeProjectFromCache(iterator.next());
+ }
+ }
+ }
+
+ /**
+ * Returns a QMakeProjectInfo for an active project configuration of a specified project.
+ *
+ * @param project the project
+ * @return the QMakeProjectInfo; or null if the project does not have QtNature
+ */
+ public static QMakeProjectInfo getQMakeProjectInfoFor(IProject project) {
+ synchronized (SYNC) {
+ QMakeProjectInfo info = CACHE.get(project);
+ if (info == null) {
+ if (QtNature.hasNature(project)) {
+ info = new QMakeProjectInfo(project);
+ CACHE.put(project,info);
+ }
+ }
+ return info;
+ }
+ }
+
+ // removes the project from the CACHE
+ private static void removeProjectFromCache(IResource project) {
+ QMakeProjectInfo info;
+ synchronized (SYNC) {
+ info = CACHE.remove(project);
+ }
+ if (info != null) {
+ info.destroy();
+ }
+ }
+
+ private final ICProjectDescription projectDescription;
+
+ // sync object for all mutable fields
+ private final Object sync = new Object();
+ // true if this instance still registered in CACHE
+ private boolean live = true;
+ // a set of sensitive files that might affects actual QMake information
+ private final SensitiveSet sensitiveFilePathSet = new SensitiveSet();
+ // an active project configuration
+ private ControllerImpl activeController;
+ // the last calculated QMake info; null if not calculated
+ private IQMakeInfo qmakeInfo = null;
+ // listeners
+ private final List<IQMakeProjectInfoListener> listeners = new CopyOnWriteArrayList<IQMakeProjectInfoListener>();
+
+ private QMakeProjectInfo(IProject project) {
+ projectDescription = CoreModel.getDefault().getProjectDescriptionManager().getProjectDescription(project);
+ CoreModel.getDefault().addCProjectDescriptionListener(this, ICDescriptionDelta.ACTIVE_CFG);
+ updateActiveConfiguration();
+ }
+
+ // called from removeProjectFromCache only
+ private void destroy() {
+ synchronized (sync) {
+ if (! live) {
+ return;
+ }
+ live = false;
+ CoreModel.getDefault().removeCProjectDescriptionListener(this);
+ removeActiveConfiguration();
+ qmakeInfo = QMakeInfo.INVALID;
+ }
+ }
+
+ // removes active configuration
+ private void removeActiveConfiguration() {
+ ControllerImpl previous = activeController;
+ activeController = null;
+ if (previous != null) {
+ previous.destroy();
+ }
+ }
+
+ // updates active configuration
+ private void updateActiveConfiguration() {
+ ICConfigurationDescription configuration = projectDescription.getActiveConfiguration();
+ if (configuration != null) {
+ activeController = new ControllerImpl(configuration);
+ }
+ scheduleFetchQMakeInfo();
+ }
+
+ // called on active project configuration change
+ @Override
+ public void handleEvent(CProjectDescriptionEvent event) {
+ synchronized (sync) {
+ removeActiveConfiguration();
+ updateActiveConfiguration();
+ }
+ }
+
+ @Override
+ public void addListener(IQMakeProjectInfoListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(IQMakeProjectInfoListener listener) {
+ listeners.remove(listener);
+ }
+
+ // calculates (if does not exist) and returns actual QMake info
+ @Override
+ public IQMakeInfo getActualInfo() {
+ synchronized (sync) {
+ if (! live) {
+ return QMakeInfo.INVALID;
+ }
+ if (qmakeInfo == null) {
+ fetchQMakeInfo();
+ }
+ return qmakeInfo;
+ }
+ }
+
+ // calculates actual QMake info
+ private void fetchQMakeInfo() {
+ // retrieves IQMakeEnvInfo from IQMakeEnv
+ IQMakeEnv qmakeEnv = activeController != null ? activeController.getQMakeEnv() : null;
+ QMakeEnvInfo qmakeEnvInfo = qmakeEnv != null ? qmakeEnv.getQMakeEnvInfo() : null;
+
+ // retrieves .pro file path
+ String proFilePath = toFilePath(qmakeEnvInfo != null ? qmakeEnvInfo.getProFile() : null);
+ // retrieves qmake executable path
+ String qmakeFilePath = qmakeEnvInfo != null ? qmakeEnvInfo.getQMakeFilePath() : null;
+ // retries environment
+ List<String> envList = new ArrayList<String>();
+ Map<String, String> envMap = qmakeEnvInfo != null ? qmakeEnvInfo.getEnvironment() : Collections.<String,String>emptyMap();
+ for (Map.Entry<String,String> entry : envMap.entrySet()) {
+ envList.add(entry.getKey() + "=" + entry.getValue());
+ }
+
+ // calculates actual QMake info
+ qmakeInfo = QMakeInfo.create(proFilePath, qmakeFilePath, envList.toArray(new String[envList.size()]));
+
+ // calculates a new set of sensitive file paths
+ sensitiveFilePathSet.clear();
+ Set<IFile> envSensFiles = qmakeEnvInfo != null ? qmakeEnvInfo.getSensitiveFiles() : Collections.<IFile>emptySet();
+ for (IFile sensitiveFile : envSensFiles) {
+ if (sensitiveFile != null) {
+ sensitiveFilePathSet.addSensitiveFile(sensitiveFile);
+ }
+ }
+ if (proFilePath != null) {
+ sensitiveFilePathSet.addSensitiveFile(proFilePath);
+ }
+ List<String> sensitiveFiles = qmakeInfo.getInvolvedQMakeFiles();
+ if (sensitiveFiles != null) {
+ for (String sensitiveFile : sensitiveFiles) {
+ sensitiveFilePathSet.addSensitiveFile(sensitiveFile);
+ }
+ }
+ }
+
+ // converts IFile to absolute path
+ private static String toFilePath(IFile file) {
+ if (file != null) {
+ IPath rawLocation = file.getRawLocation();
+ if (rawLocation != null) {
+ rawLocation = rawLocation.makeAbsolute();
+ if (rawLocation != null) {
+ File f = rawLocation.toFile();
+ if (f != null) {
+ return f.getAbsolutePath();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ // checks if any of the specified files is a sensitive file
+ private boolean containsAnySensitiveFile(Set<IPath> files) {
+ synchronized (sync) {
+ if (live) {
+ for (Iterator<IPath> iterator = files.iterator(); iterator.hasNext();) {
+ IPath path = iterator.next();
+ if (sensitiveFilePathSet.contains(path)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ // resets actual QMake info and notifies all listeners that QMake information has changes
+ private void scheduleFetchQMakeInfo() {
+ synchronized (sync) {
+ if (! live) {
+ return;
+ }
+ qmakeInfo = null;
+ }
+ for (IQMakeProjectInfoListener listener : listeners) {
+ listener.qmakeInfoChanged();
+ }
+ }
+
+ /**
+ * Represents a project configuration.
+ */
+ private final class ControllerImpl implements IQMakeEnvProvider.IController {
+
+ private final ICConfigurationDescription configuration;
+ private final IQMakeEnv qmakeEnv;
+
+ public ControllerImpl(ICConfigurationDescription configuration) {
+ this.configuration = configuration;
+ // qmakeEnv created from registry of qmakeEnvProvider extensions
+ this.qmakeEnv = QMakeEnvProviderManager.getInstance().createEnv(this);
+ }
+
+ public void destroy() {
+ qmakeEnv.destroy();
+ }
+
+ public IQMakeEnv getQMakeEnv() {
+ return qmakeEnv;
+ }
+
+ @Override
+ public ICConfigurationDescription getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ public void scheduleUpdate() {
+ scheduleFetchQMakeInfo();
+ }
+
+ }
+
+ /**
+ * Listens on Eclipse file system changes.
+ */
+ private static final class RCListener implements IResourceChangeListener {
+
+ @Override
+ public void resourceChanged(IResourceChangeEvent event) {
+ RDVisitor visitor = new RDVisitor();
+
+ // collect project to delete and changed files
+ switch (event.getType()) {
+ case IResourceChangeEvent.PRE_CLOSE:
+ case IResourceChangeEvent.PRE_DELETE:
+ IResource project = event.getResource();
+ if (project != null && project.getType() == IResource.PROJECT) {
+ visitor.addProjectToDelete(project);
+ }
+ break;
+ case IResourceChangeEvent.POST_CHANGE:
+ IResourceDelta delta = event.getDelta();
+ if (delta != null) {
+ try {
+ delta.accept(visitor);
+ } catch (CoreException e) {
+ // empty
+ }
+ }
+ break;
+ }
+
+ // process collected data
+ visitor.process();
+ }
+
+ }
+
+ private static final class RDVisitor implements IResourceDeltaVisitor {
+
+ private final Set<IResource> projectsToDelete = new HashSet<IResource>();
+ private final Set<IPath> changedFiles = new HashSet<IPath>();
+
+ @Override
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ IResource resource = delta.getResource();
+ if (resource != null) {
+ switch (resource.getType()) {
+ case IResource.FILE:
+ addChangedFile(resource);
+ return false;
+ case IResource.PROJECT:
+ if (delta.getKind() == IResourceDelta.REMOVED) {
+ addProjectToDelete(resource);
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ private void addProjectToDelete(IResource project) {
+ projectsToDelete.add(project);
+ }
+
+ private void addChangedFile(IResource file) {
+ IPath fullPath = file.getFullPath();
+ if (fullPath != null) {
+ changedFiles.add(fullPath);
+ }
+ }
+
+ public void process() {
+ // removing projects from CACHE
+ for(IResource project : projectsToDelete) {
+ removeProjectFromCache(project);
+ }
+
+ List<QMakeProjectInfo> infos;
+ synchronized (SYNC) {
+ infos = new ArrayList<QMakeProjectInfo>(CACHE.values());
+ }
+ for (QMakeProjectInfo info : infos) {
+ // checking if any of the changed files affects QMakeProjectInfo
+ if (info.containsAnySensitiveFile(changedFiles)) {
+ // if so then scheduling update
+ info.scheduleFetchQMakeInfo();
+ }
+ }
+ }
+
+ }
+
+ private static final class SensitiveSet extends HashSet<IPath> {
+
+ // adds a sensitive file in form of a specified absolute path
+ private void addSensitiveFile(String sensitiveFile) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IFile[] files = root.findFilesForLocation(Path.fromOSString(sensitiveFile));
+ if (files != null && files.length > 0) {
+ IFile file = files[0];
+ addSensitiveFile(file);
+ }
+ }
+
+ // adds a sensitive file in form of a IFile
+ private void addSensitiveFile(IFile file) {
+ IPath fullPath = file.getFullPath();
+ if (fullPath != null) {
+ add(fullPath);
+ }
+ }
+
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeVersion.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeVersion.java
new file mode 100644
index 0000000..b3052be
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QMakeVersion.java
@@ -0,0 +1,63 @@
+/*
+ * 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.index;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.qt.core.QtPlugin;
+import org.eclipse.cdt.qt.core.index.IQtVersion;
+
+/**
+ * A container class to interpret and store value of the the qmake version.
+ */
+public final class QMakeVersion implements IQtVersion {
+
+ // QMAKE_VERSION looks like 2.01a or 3.0
+ private static final Pattern REGEXP = Pattern.compile( "([\\d]+)\\.([\\d]+).*" );
+
+ // parses major and minor version numbers only
+ public static QMakeVersion create(String version) {
+ if (version == null) {
+ return null;
+ }
+
+ Matcher m = REGEXP.matcher(version.trim());
+ if (!m.matches()) {
+ return null;
+ }
+
+ try {
+ int major = Integer.parseInt(m.group(1));
+ int minor = Integer.parseInt(m.group(2));
+ return new QMakeVersion(major, minor);
+ } catch(NumberFormatException e) {
+ QtPlugin.log(e);
+ }
+ return null;
+ }
+
+ private final int major;
+ private final int minor;
+
+ private QMakeVersion(int major, int minor) {
+ this.major = major;
+ this.minor = minor;
+ }
+
+ @Override
+ public int getMajor() {
+ return major;
+ }
+
+ @Override
+ public int getMinor() {
+ return minor;
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtNature.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtNature.java
index f58e2cd..69c2df2 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtNature.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtNature.java
@@ -16,7 +16,16 @@ import org.eclipse.core.runtime.CoreException;
public class QtNature implements IProjectNature {
public static final String ID = "org.eclipse.cdt.qt.core.qtNature";
-
+
+ public static boolean hasNature(IProject project) {
+ try {
+ return project.hasNature(ID);
+ } catch (CoreException e) {
+ QtPlugin.log(e);
+ return false;
+ }
+ }
+
private IProject project;
@Override
@@ -36,5 +45,5 @@ public class QtNature implements IProjectNature {
public void setProject(IProject project) {
this.project = project;
}
-
+
}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java
index 825b561..f11e1b2 100644
--- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtPlugin.java
@@ -1,9 +1,13 @@
package org.eclipse.cdt.qt.core;
-import org.osgi.framework.BundleActivator;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.internal.qt.core.index.QMakeProjectInfo;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
import org.osgi.framework.BundleContext;
-public class QtPlugin implements BundleActivator {
+public class QtPlugin extends Plugin {
public static final String ID = "org.eclipse.cdt.qt.core";
public static final String SIGNAL_SLOT_TAGGER_ID = ID + ".signalslot.tagger";
@@ -11,19 +15,29 @@ public class QtPlugin implements BundleActivator {
public static final int SignalSlot_Mask_signal = 1;
public static final int SignalSlot_Mask_slot = 2;
+ public static final String QMAKE_ENV_PROVIDER_EXT_POINT_NAME = "qmakeEnvProvider"; //$NON-NLS-1$
+ public static final String QMAKE_ENV_PROVIDER_ID = ID + "." + QMAKE_ENV_PROVIDER_EXT_POINT_NAME; //$NON-NLS-1$
+
+ private static QtPlugin INSTANCE;
private static BundleContext context;
static BundleContext getContext() {
return context;
}
+ static QtPlugin getDefault() {
+ return INSTANCE;
+ }
+
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
@Override
public void start(BundleContext bundleContext) throws Exception {
+ INSTANCE = this;
QtPlugin.context = bundleContext;
+ QMakeProjectInfo.start();
}
/*
@@ -32,7 +46,34 @@ public class QtPlugin implements BundleActivator {
*/
@Override
public void stop(BundleContext bundleContext) throws Exception {
+ QMakeProjectInfo.stop();
QtPlugin.context = null;
+ INSTANCE = null;
+ }
+
+ public static void log(String e) {
+ log(IStatus.INFO, e, null);
+ }
+
+ public static void log(Throwable e) {
+ String msg= e.getMessage();
+ if (msg == null) {
+ log("Error", e); //$NON-NLS-1$
+ } else {
+ log("Error: " + msg, e); //$NON-NLS-1$
+ }
+ }
+
+ public static void log(String message, Throwable e) {
+ Throwable nestedException;
+ if (e instanceof CModelException && (nestedException = ((CModelException)e).getException()) != null) {
+ e = nestedException;
+ }
+ log(IStatus.ERROR, message, e);
+ }
+
+ public static void log(int code, String msg, Throwable e) {
+ getDefault().getLog().log(new Status(code, ID, msg, e));
}
}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnv.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnv.java
new file mode 100644
index 0000000..574d3fb
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnv.java
@@ -0,0 +1,27 @@
+/*
+ * 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.qt.core.index;
+
+/**
+ * Represents a QMake environment. It is usually created by IQMakeEnvProvider.createEnv() method for a specific project configuration.
+ */
+public interface IQMakeEnv {
+
+ /**
+ * Notifies that this environment is no longer used.
+ */
+ void destroy();
+
+ /**
+ * Returns an actual QMake environment information that is used for a single qmake run to retrieve QMake information.
+ *
+ * @return the actual QMake environment information
+ */
+ QMakeEnvInfo getQMakeEnvInfo();
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnvProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnvProvider.java
new file mode 100644
index 0000000..2dd5053
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeEnvProvider.java
@@ -0,0 +1,49 @@
+/*
+ * 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.qt.core.index;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+
+/**
+ * Represents a provider for IQMakeEnv which is used to specify an environment for qmake run.
+ * This class needs to be registered via org.eclipse.cdt.qt.core.qmakeEnvProvider extension point.
+ */
+public interface IQMakeEnvProvider {
+
+ /**
+ * Creates a QMake environment for a specific IController (aka a project configuration).
+ *
+ * @param controller the controller
+ * @return the IQMakeEnv instance that is used for qmake run;
+ * or null if this provider cannot create IQMakeEnv instance for the specified IController.
+ */
+ IQMakeEnv createEnv(IController controller);
+
+ /**
+ * Represents a project configuration and provides a control over the environment.
+ *
+ * This class is not meant to be implemented.
+ */
+ public interface IController {
+
+ /**
+ * Returns a project configuration for which a QMake environment should be supplied.
+ *
+ * @return the project configuration
+ */
+ ICConfigurationDescription getConfiguration();
+
+ /**
+ * Request the controller to schedule a new qmake run to retrieve new QMake information.
+ * This method should be called when there is any change in IQMakeEnv that might affect resulting IQMakeEnvInfo.
+ */
+ void scheduleUpdate();
+
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeInfo.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeInfo.java
new file mode 100644
index 0000000..2b8cd5d
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeInfo.java
@@ -0,0 +1,92 @@
+/*
+ * 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.qt.core.index;
+
+import java.util.List;
+
+/**
+ * Represents a QMake information.
+ *
+ * Note that current implementation of does not handle support QMake 2.0 in full range so provided information might be incomplete.
+ *
+ * This class is not meant to be implemented.
+ */
+public interface IQMakeInfo {
+
+ /**
+ * Returns whether this information is valid. If invalid, then returned value of the other method is unspecified.
+ *
+ * @return true if this information is valid
+ */
+ boolean isValid();
+
+ /**
+ * Returns a Qt version as provided by "qmake -query" command.
+ *
+ * @return the Qt version
+ */
+ IQtVersion getQtVersion();
+
+ /**
+ * Returns a list of QMake files (.pro, .pri, .prf, ...) that are involved in resolving this information as retrieved
+ * via "qmake -E file.pro" command.
+ *
+ * @return the list of involved QMake files
+ */
+ List<String> getInvolvedQMakeFiles();
+
+ /**
+ * Returns a list of Qt Import paths. Represents QT_IMPORT_PATH that is used by QDeclarativeEngine (aka QtQuick1) runtime to load QML modules.
+ *
+ * @return the list of Qt Import paths
+ */
+ List<String> getQtImportPath();
+
+ /**
+ * Returns a list of Qt Qml paths that is used by QQmlEngine (aka QtQuick2) runtime to load QML modules.
+ *
+ * @return the list of Qt Qml paths
+ */
+ List<String> getQtQmlPath();
+
+ /**
+ * Returns a list of include paths that are used for compilation of a related project.
+ *
+ * @return the list of include paths
+ */
+ List<String> getIncludePath();
+
+ /**
+ * Returns a list of defines that are used for compilation of a related project i.e. specified via DEFINES QMake variable.
+ *
+ * @return the list of defines.
+ */
+ List<String> getDefines();
+
+ /**
+ * Returns a list of source file paths i.e. specified via SOURCES QMake variable.
+ *
+ * @return the list of source file paths
+ */
+ List<String> getSourceFiles();
+
+ /**
+ * Returns a list of header file paths i.e. specified via HEADERS QMake variable.
+ *
+ * @return the list of header file paths
+ */
+ List<String> getHeaderFiles();
+
+ /**
+ * Returns a list of other file paths i.e. specified via OTHER_FILES QMake variable.
+ *
+ * @return the list of other file paths
+ */
+ List<String> getOtherFiles();
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfo.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfo.java
new file mode 100644
index 0000000..60edc76
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfo.java
@@ -0,0 +1,40 @@
+/*
+ * 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.qt.core.index;
+
+/**
+ * Represents provider of QMake information.
+ *
+ * This class is not meant to be implemented.
+ */
+public interface IQMakeProjectInfo {
+
+ /**
+ * Add a listener that notifies about possible changes of IQMakeInfo retrieved from getActualInfo() method.
+ *
+ * @param listener the listener
+ */
+ void addListener(IQMakeProjectInfoListener listener);
+
+ /**
+ * Removes a listener that was added via addListener() method.
+ *
+ * @param listener the listener
+ */
+ void removeListener(IQMakeProjectInfoListener listener);
+
+ /**
+ * Returns an actual QMake information.
+ *
+ * Note that this is a long-term operation and the method call is blocked until an actual QMake information is calculated.
+ *
+ * @return non-null IQMakeInfo instance representing the actual QMake information
+ */
+ IQMakeInfo getActualInfo();
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfoListener.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfoListener.java
new file mode 100644
index 0000000..ba132f0
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQMakeProjectInfoListener.java
@@ -0,0 +1,21 @@
+/*
+ * 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.qt.core.index;
+
+/**
+ * A listener used for notifying that a QMake information provided by IQMakeProjectInfo might have changed.
+ */
+public interface IQMakeProjectInfoListener {
+
+ /**
+ * Notifies that a QMake information provided by IQMakeProjectInfo might have changed.
+ * A new QMake information can be read via IQMakeProjectInfo.getQMakeInfo() method.
+ */
+ void qmakeInfoChanged();
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQtVersion.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQtVersion.java
new file mode 100644
index 0000000..5acdc93
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/IQtVersion.java
@@ -0,0 +1,27 @@
+/*
+ * 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.qt.core.index;
+
+/**
+ * Represents a Qt version in form of major and minor number.
+ */
+public interface IQtVersion {
+
+ /**
+ * Returns major version number.
+ * @return the major version number
+ */
+ int getMajor();
+
+ /**
+ * Returns minor version number.
+ * @return the minor version number
+ */
+ int getMinor();
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeEnvInfo.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeEnvInfo.java
new file mode 100644
index 0000000..cd7dee6
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeEnvInfo.java
@@ -0,0 +1,81 @@
+/*
+ * 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.qt.core.index;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * Holds data describing QMake environment (pro file, qmake file, env. vars.) for a specific QMake run provided by QMakeEnv instance.
+ */
+public final class QMakeEnvInfo {
+
+ private final IFile proFile;
+ private final String qmakeFilePath;
+ private final Map<String, String> environment;
+ private final Set<IFile> sensitiveFiles;
+
+ /**
+ * Creates QMakeEnvInfo.
+ *
+ * @param proFile the root-level .pro file
+ * @param qmakeFilePath the absolute path of qmake executable
+ * @param environment environment variables
+ * @param sensitiveFiles the list of IFile that needs to be tracked by IQMakeProjectInfo since their change might affect
+ * an environment for running qmake.
+ */
+ public QMakeEnvInfo(IFile proFile, String qmakeFilePath, Map<String,String> environment, Collection<IFile> sensitiveFiles) {
+ this.proFile = proFile;
+ this.qmakeFilePath = qmakeFilePath;
+ this.environment = environment != null ? new HashMap<String,String>(environment) : Collections.<String,String>emptyMap();
+ this.sensitiveFiles = sensitiveFiles != null ? new HashSet<IFile>(sensitiveFiles) : Collections.<IFile>emptySet();
+ }
+
+ /**
+ * Returns IFile of .pro file.
+ *
+ * @return the .pro file
+ */
+ public IFile getProFile() {
+ return proFile;
+ }
+
+ /**
+ * Returns an absolute path of qmake executable.
+ *
+ * @return the qmake path
+ */
+ public String getQMakeFilePath() {
+ return qmakeFilePath;
+ }
+
+ /**
+ * Returns a map of environment variables that are used for qmake run.
+ *
+ * @return the environment
+ */
+ public Map<String, String> getEnvironment() {
+ return environment;
+ }
+
+ /**
+ * Returns a list of IFile that might affect environment of qmake run.
+ *
+ * @return the list sensitive files
+ */
+ public Set<IFile> getSensitiveFiles() {
+ return sensitiveFiles;
+ }
+
+}
diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeProjectInfoFactory.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeProjectInfoFactory.java
new file mode 100644
index 0000000..758b713
--- /dev/null
+++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/index/QMakeProjectInfoFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.qt.core.index;
+
+import org.eclipse.cdt.internal.qt.core.index.QMakeProjectInfo;
+import org.eclipse.core.resources.IProject;
+
+/**
+ * A factory for QMakeProjectInfo instances.
+ */
+public final class QMakeProjectInfoFactory {
+
+ private QMakeProjectInfoFactory() {
+ }
+
+ /**
+ * Provides a IQMakeProjectInfo for an active project configuration
+ * in a specified project.
+ *
+ * @param project the project
+ * @return IQMakeProjectInfo representing an activate project configuration
+ * in the specified project.
+ */
+ public static IQMakeProjectInfo getForActiveConfigurationIn(IProject project) {
+ return QMakeProjectInfo.getQMakeProjectInfoFor(project);
+ }
+
+}