mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-10 09:45:39 +02:00
Bug 422797 - API for retrieving QMake information from Qt project
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>
This commit is contained in:
parent
f887c8e671
commit
026b9325f0
21 changed files with 1730 additions and 6 deletions
|
@ -7,8 +7,10 @@ Bundle-Activator: org.eclipse.cdt.qt.core.QtPlugin
|
||||||
Bundle-Vendor: Eclipse CDT
|
Bundle-Vendor: Eclipse CDT
|
||||||
Require-Bundle: org.eclipse.core.runtime,
|
Require-Bundle: org.eclipse.core.runtime,
|
||||||
org.eclipse.core.resources,
|
org.eclipse.core.resources,
|
||||||
|
org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
|
||||||
org.eclipse.cdt.core
|
org.eclipse.cdt.core
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
Export-Package: org.eclipse.cdt.qt.core
|
Export-Package: org.eclipse.cdt.qt.core,
|
||||||
|
org.eclipse.cdt.qt.core.index
|
||||||
|
|
|
@ -5,4 +5,5 @@ bin.includes = META-INF/,\
|
||||||
plugin.xml,\
|
plugin.xml,\
|
||||||
templates/,\
|
templates/,\
|
||||||
about.html
|
about.html
|
||||||
src.includes = about.html
|
src.includes = about.html,\
|
||||||
|
schema/
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
qtProjectFile.name = Qt Project File
|
qtProjectFile.name = Qt Project File
|
||||||
qmlFile.name = QML File
|
qmlFile.name = QML File
|
||||||
|
qmakeEnvProvider.name = QMake Environment Provider
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<?eclipse version="3.4"?>
|
<?eclipse version="3.4"?>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
<extension-point id="qmakeEnvProvider" name="%qmakeEnvProvider.name" schema="schema/qmakeEnvProvider.exsd"/>
|
||||||
|
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.cdt.core.templates">
|
point="org.eclipse.cdt.core.templates">
|
||||||
<template
|
<template
|
||||||
|
|
136
qt/org.eclipse.cdt.qt.core/schema/qmakeEnvProvider.exsd
Normal file
136
qt/org.eclipse.cdt.qt.core/schema/qmakeEnvProvider.exsd
Normal file
|
@ -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:
|
||||||
|
<p>
|
||||||
|
<pre>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.cdt.qt.core.qmakeEnvProvider"
|
||||||
|
id="example"
|
||||||
|
name="Example QMake Env Provider Extension">
|
||||||
|
<qmakeEnvProvider
|
||||||
|
class="com.example.internal.ExampleProvider">
|
||||||
|
<enablement>
|
||||||
|
<with variable="projectNatures">
|
||||||
|
<iterate operator="or">
|
||||||
|
<equals value="com.example.my-nature"/>
|
||||||
|
</iterate>
|
||||||
|
</with>
|
||||||
|
</enablement>
|
||||||
|
</qmakeEnvProvider>
|
||||||
|
</extension>
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appinfo>
|
||||||
|
<meta.section type="apiinfo"/>
|
||||||
|
</appinfo>
|
||||||
|
<documentation>
|
||||||
|
The contributed class must implement <code>org.eclipse.cdt.qt.core.index.IQMakeEnvProvider</code>.
|
||||||
|
</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>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,16 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
public class QtNature implements IProjectNature {
|
public class QtNature implements IProjectNature {
|
||||||
public static final String ID = "org.eclipse.cdt.qt.core.qtNature";
|
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;
|
private IProject project;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,5 +45,5 @@ public class QtNature implements IProjectNature {
|
||||||
public void setProject(IProject project) {
|
public void setProject(IProject project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
package org.eclipse.cdt.qt.core;
|
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;
|
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 ID = "org.eclipse.cdt.qt.core";
|
||||||
public static final String SIGNAL_SLOT_TAGGER_ID = ID + ".signalslot.tagger";
|
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_signal = 1;
|
||||||
public static final int SignalSlot_Mask_slot = 2;
|
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;
|
private static BundleContext context;
|
||||||
|
|
||||||
static BundleContext getContext() {
|
static BundleContext getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QtPlugin getDefault() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
|
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void start(BundleContext bundleContext) throws Exception {
|
public void start(BundleContext bundleContext) throws Exception {
|
||||||
|
INSTANCE = this;
|
||||||
QtPlugin.context = bundleContext;
|
QtPlugin.context = bundleContext;
|
||||||
|
QMakeProjectInfo.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -32,7 +46,34 @@ public class QtPlugin implements BundleActivator {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void stop(BundleContext bundleContext) throws Exception {
|
public void stop(BundleContext bundleContext) throws Exception {
|
||||||
|
QMakeProjectInfo.stop();
|
||||||
QtPlugin.context = null;
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue