mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 08:55:25 +02:00
Bug 422797 - API for retrieving QMake information from Qt project
Adding a new IQMakeInfo getter: * getQMakeQueryMap() * getQtDocPath() * getResourceFiles() * getFormFiles() Fixing incorrect parsing of OTHER_FILES variable. Adding QMakeTests.testQMakeInfo() JUnit test for qmake output parser. Change-Id: Ic4e0180381967e2a96455d6a3411fe51ce1cef91 Signed-off-by: David Kaspar <dkaspar@blackberry.com> Reviewed-on: https://git.eclipse.org/r/20500 Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com> Tested-by: Doug Schaefer <dschaefer@qnx.com>
This commit is contained in:
parent
e9b3224eaa
commit
5927d7ea30
6 changed files with 131 additions and 53 deletions
|
@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.core.runtime,
|
|||
org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
|
||||
org.eclipse.cdt.core,
|
||||
org.eclipse.cdt.codan.core,
|
||||
org.eclipse.cdt.codan.core.cxx
|
||||
org.eclipse.cdt.codan.core.cxx,
|
||||
org.eclipse.core.filesystem
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Localization: plugin
|
||||
|
|
|
@ -35,37 +35,47 @@ public final class QMakeInfo implements IQMakeInfo {
|
|||
/**
|
||||
* 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());
|
||||
public static final IQMakeInfo INVALID = new QMakeInfo(false, Collections.<String,String>emptyMap(), Collections.<String,String>emptyMap());
|
||||
|
||||
private final boolean valid;
|
||||
private final Map<String, String> qmakeQueryMap;
|
||||
private final IQtVersion qtVersion;
|
||||
private final List<String> involvedQMakeFiles;
|
||||
private final List<String> qtImportPath;
|
||||
private final List<String> qtQmlPath;
|
||||
private final List<String> qtDocPath;
|
||||
private final List<String> includePath;
|
||||
private final List<String> defines;
|
||||
private final List<String> sourceFiles;
|
||||
private final List<String> headerFiles;
|
||||
private final List<String> resourceFiles;
|
||||
private final List<String> formFiles;
|
||||
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) {
|
||||
public QMakeInfo(boolean valid, Map<String,String> queryMap, Map<String,String> proMap) {
|
||||
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);
|
||||
}
|
||||
this.qmakeQueryMap = Collections.unmodifiableMap(queryMap);
|
||||
|
||||
public static IQMakeInfo create(File projectFile, File qmake, String[] extraEnv) {
|
||||
return create(projectFile.getAbsolutePath(), qmake.getAbsolutePath(), extraEnv);
|
||||
this.qtVersion = QMakeVersion.create(queryMap.get(QMakeParser.KEY_QT_VERSION));
|
||||
List<String> tmpQtImportPaths = new ArrayList<String>(QMakeParser.singleValue(queryMap, QMakeParser.KEY_QT_INSTALL_IMPORTS));
|
||||
List<String> tmpQtQmlPaths = new ArrayList<String>(QMakeParser.singleValue(queryMap, QMakeParser.KEY_QT_INSTALL_QML));
|
||||
this.qtDocPath = QMakeParser.singleValue(queryMap, QMakeParser.KEY_QT_INSTALL_DOCS);
|
||||
|
||||
this.involvedQMakeFiles = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_QMAKE_INTERNAL_INCLUDED_FILES);
|
||||
this.includePath = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_INCLUDEPATH);
|
||||
this.defines = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_DEFINES);
|
||||
this.sourceFiles = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_SOURCES);
|
||||
this.headerFiles = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_HEADERS);
|
||||
this.resourceFiles = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_RESOURCES);
|
||||
this.formFiles = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_FORMS);
|
||||
this.otherFiles = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_OTHER_FILES);
|
||||
|
||||
// combine qtImportPath and qtQmlPath from both qmake runs
|
||||
List<String> qmlImportPath = QMakeParser.qmake3DecodeValueList(proMap, QMakeParser.KEY_QML_IMPORT_PATH);
|
||||
tmpQtImportPaths.addAll(qmlImportPath);
|
||||
tmpQtQmlPaths.addAll(qmlImportPath);
|
||||
this.qtImportPath = Collections.unmodifiableList(tmpQtImportPaths);
|
||||
this.qtQmlPath = Collections.unmodifiableList(tmpQtQmlPaths);
|
||||
}
|
||||
|
||||
public static IQMakeInfo create(String proPath, String qmakePath, String[] extraEnv) {
|
||||
|
@ -75,35 +85,17 @@ public final class QMakeInfo implements IQMakeInfo {
|
|||
|
||||
// run "qmake -query"
|
||||
Map<String, String> qmake1 = exec(PATTERN_QUERY_LINE, extraEnv, qmakePath, "-query");
|
||||
if (qmake1 == null)
|
||||
if (qmake1 == null) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
// check the qmake version
|
||||
// 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);
|
||||
return new QMakeInfo(true, qmake1, qmake2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,9 +103,14 @@ public final class QMakeInfo implements IQMakeInfo {
|
|||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getQMakeQueryMap() {
|
||||
return qmakeQueryMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IQtVersion getQtVersion() {
|
||||
return qtVersion;
|
||||
return qtVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,6 +128,11 @@ public final class QMakeInfo implements IQMakeInfo {
|
|||
return qtQmlPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getQtDocPath() {
|
||||
return qtDocPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getIncludePath() {
|
||||
return includePath;
|
||||
|
@ -152,9 +154,19 @@ public final class QMakeInfo implements IQMakeInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOtherFiles() {
|
||||
public List<String> getResourceFiles() {
|
||||
return resourceFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFormFiles() {
|
||||
return formFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOtherFiles() {
|
||||
return otherFiles;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a command and parses its output into a map.
|
||||
|
@ -164,7 +176,6 @@ public final class QMakeInfo implements IQMakeInfo {
|
|||
* @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] : ""));
|
||||
|
|
|
@ -28,11 +28,15 @@ public final class QMakeParser {
|
|||
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_QT_INSTALL_DOCS = "QT_INSTALL_DOCS";
|
||||
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_RESOURCES = "RESOURCES";
|
||||
public static final String KEY_FORMS = "FORMS";
|
||||
public static final String KEY_OTHER_FILES = "OTHER_FILES";
|
||||
public static final String KEY_QML_IMPORT_PATH = "QML_IMPORT_PATH";
|
||||
|
||||
/**
|
||||
|
@ -40,7 +44,7 @@ public final class QMakeParser {
|
|||
*
|
||||
* @param regex the reg. exp.
|
||||
* @param reader the QMake output
|
||||
* @return the map of parsed key-value pairs
|
||||
* @return the modifiable map of parsed key-value pairs
|
||||
* @throws IOException when io error happens
|
||||
*/
|
||||
public static Map<String, String> parse(Pattern regex, BufferedReader reader) throws IOException {
|
||||
|
@ -64,11 +68,11 @@ public final class QMakeParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list with 0-1 values for a specific QMake variable.
|
||||
* Returns an unmodifiable list with 0-1 values for a specific QMake variable.
|
||||
*
|
||||
* @param map the map
|
||||
* @param key the QMake variable
|
||||
* @return the list of values
|
||||
* @return the unmodifiable list of values
|
||||
*/
|
||||
public static List<String> singleValue(Map<String, String> map, String key) {
|
||||
String value = map.get(key);
|
||||
|
@ -76,11 +80,11 @@ public final class QMakeParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of values for a specific QMake variable that is decoded as a list of values.
|
||||
* Returns an unmodifiable 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
|
||||
* @return the unmodifiable list of values
|
||||
*/
|
||||
public static List<String> qmake3DecodeValueList(Map<String, String> map, String key) {
|
||||
String value = map.get(key);
|
||||
|
@ -92,7 +96,7 @@ public final class QMakeParser {
|
|||
for (String item : qmake3SplitValueList(value)) {
|
||||
result.add(qmake3DecodeValue(item));
|
||||
}
|
||||
return result;
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,7 +155,7 @@ public final class QMakeParser {
|
|||
* Splits a specified QMake variable value into a list of values.
|
||||
*
|
||||
* @param value the value
|
||||
* @return the list of values
|
||||
* @return the modifiable list of values
|
||||
*/
|
||||
private static List<String> qmake3SplitValueList(String value) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
|
|
|
@ -31,6 +31,7 @@ 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.filesystem.URIUtil;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
|
@ -410,10 +411,12 @@ public final class QMakeProjectInfo implements IQMakeProjectInfo, ICProjectDescr
|
|||
|
||||
private static final class SensitiveSet extends HashSet<IPath> {
|
||||
|
||||
private static final long serialVersionUID = 2684086006933209512L;
|
||||
|
||||
// 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));
|
||||
IFile[] files = root.findFilesForLocationURI(URIUtil.toURI(Path.fromOSString(sensitiveFile).makeAbsolute()));
|
||||
if (files != null && files.length > 0) {
|
||||
IFile file = files[0];
|
||||
addSensitiveFile(file);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
package org.eclipse.cdt.qt.core.index;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a QMake information.
|
||||
|
@ -25,6 +26,13 @@ public interface IQMakeInfo {
|
|||
*/
|
||||
boolean isValid();
|
||||
|
||||
/**
|
||||
* Returns a map of key-value pairs provided by "qmake -query" command.
|
||||
*
|
||||
* @return the map
|
||||
*/
|
||||
Map<String,String> getQMakeQueryMap();
|
||||
|
||||
/**
|
||||
* Returns a Qt version as provided by "qmake -query" command.
|
||||
*
|
||||
|
@ -54,6 +62,13 @@ public interface IQMakeInfo {
|
|||
*/
|
||||
List<String> getQtQmlPath();
|
||||
|
||||
/**
|
||||
* Returns a list of Qt Documentation paths.
|
||||
*
|
||||
* @return the list of Qt Documentation paths
|
||||
*/
|
||||
List<String> getQtDocPath();
|
||||
|
||||
/**
|
||||
* Returns a list of include paths that are used for compilation of a related project.
|
||||
*
|
||||
|
@ -82,6 +97,20 @@ public interface IQMakeInfo {
|
|||
*/
|
||||
List<String> getHeaderFiles();
|
||||
|
||||
/**
|
||||
* Returns a list of resource file paths i.e. specified via RESOURCES QMake variable.
|
||||
*
|
||||
* @return the list of other file paths
|
||||
*/
|
||||
List<String> getResourceFiles();
|
||||
|
||||
/**
|
||||
* Returns a list of other file paths i.e. specified via FORMS QMake variable.
|
||||
*
|
||||
* @return the list of other file paths
|
||||
*/
|
||||
List<String> getFormFiles();
|
||||
|
||||
/**
|
||||
* Returns a list of other file paths i.e. specified via OTHER_FILES QMake variable.
|
||||
*
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.eclipse.cdt.qt.tests;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -17,6 +18,7 @@ import junit.framework.TestCase;
|
|||
import org.eclipse.cdt.internal.qt.core.index.QMakeInfo;
|
||||
import org.eclipse.cdt.internal.qt.core.index.QMakeParser;
|
||||
import org.eclipse.cdt.internal.qt.core.index.QMakeVersion;
|
||||
import org.eclipse.cdt.qt.core.index.IQMakeInfo;
|
||||
|
||||
public class QMakeTests extends TestCase {
|
||||
|
||||
|
@ -40,7 +42,7 @@ public class QMakeTests extends TestCase {
|
|||
assertEquals(0, three_dot_zero.getMinor());
|
||||
}
|
||||
|
||||
public void testQMakeInfo() throws Exception {
|
||||
public void testQMake3Decoder() throws Exception {
|
||||
StringReader content = new StringReader("A = \\\\\\\"\nB = A\\n\\tB\nC = \"A \\\" B\" \"A \\\" B\"");
|
||||
BufferedReader reader = new BufferedReader(content);
|
||||
|
||||
|
@ -64,4 +66,32 @@ public class QMakeTests extends TestCase {
|
|||
assertEquals(0, D.size());
|
||||
}
|
||||
|
||||
public void testQMakeInfo() throws Exception {
|
||||
StringReader qmake1Content = new StringReader("QMAKE_VERSION:3.0\nQT_VERSION:5.2\nQT_INSTALL_IMPORTS:QtImports\nQT_INSTALL_QML:QtQmls\nQT_INSTALL_DOCS:QtDocs\nCustomKey:CustomValue\n");
|
||||
BufferedReader qmake1Reader = new BufferedReader(qmake1Content);
|
||||
Map<String, String> qmake1 = QMakeParser.parse(QMakeInfo.PATTERN_QUERY_LINE, qmake1Reader);
|
||||
|
||||
StringReader qmake2Content = new StringReader("QMAKE_INTERNAL_INCLUDED_FILES=Internal1 Internal2\nSOURCES=Source1 Source2\nHEADERS=Header1 Header2\nINCLUDEPATH=Include1 Include2\nDEFINES=Def1 Def2\nRESOURCES=Resource1 Resource2\nFORMS=Form1 Form2\nOTHER_FILES=Other1 Other2\nQML_IMPORT_PATH=CustomImport\n");
|
||||
BufferedReader qmake2Reader = new BufferedReader(qmake2Content);
|
||||
Map<String, String> qmake2 = QMakeParser.parse(QMakeInfo.PATTERN_EVAL_LINE, qmake2Reader);
|
||||
|
||||
IQMakeInfo info = new QMakeInfo(true, qmake1, qmake2);
|
||||
|
||||
assertNotNull(info);
|
||||
assertEquals(5, info.getQtVersion().getMajor());
|
||||
assertEquals(2, info.getQtVersion().getMinor());
|
||||
assertEquals(Arrays.asList("QtImports", "CustomImport"), info.getQtImportPath());
|
||||
assertEquals(Arrays.asList("QtQmls", "CustomImport"), info.getQtQmlPath());
|
||||
assertEquals(Arrays.asList("QtDocs"), info.getQtDocPath());
|
||||
assertEquals("CustomValue", info.getQMakeQueryMap().get("CustomKey"));
|
||||
|
||||
assertEquals(Arrays.asList("Include1", "Include2"), info.getIncludePath());
|
||||
assertEquals(Arrays.asList("Def1", "Def2"), info.getDefines());
|
||||
assertEquals(Arrays.asList("Header1", "Header2"), info.getHeaderFiles());
|
||||
assertEquals(Arrays.asList("Source1", "Source2"), info.getSourceFiles());
|
||||
assertEquals(Arrays.asList("Resource1", "Resource2"), info.getResourceFiles());
|
||||
assertEquals(Arrays.asList("Form1", "Form2"), info.getFormFiles());
|
||||
assertEquals(Arrays.asList("Other1", "Other2"), info.getOtherFiles());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue