/*******************************************************************************
* Copyright (c) 2015 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
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.pro.parser;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
/**
* Very basic parser for Qt Project Files that uses regular expressions. For now, this class only supports finding variables within
* a Document that follow the syntax:
*
* <pre>
* <code>VARIABLE_NAME += value1 \ # comment
* value2 \ # comment
* value3</code>
* </pre>
*
* The assignment operator may be one of =, +=, -=, or *= in accordance with qmake syntax. Variable names are not checked for
* semantic validity. That is, this class does not make sure the variable name is a registered qmake variable, nor that there are
* multiple instances of a variable in the document.
*/
public class QtProjectFileParser implements IDocumentListener {
IDocument document;
List<QtProjectVariable> variables;
public QtProjectFileParser(IDocument doc) {
if (doc == null) {
throw new IllegalArgumentException("document cannot be null"); //$NON-NLS-1$
}
document = doc;
variables = parse();
document.addDocumentListener(this);
}
public IDocument getDocument() {
return document;
}
private List<QtProjectVariable> parse() {
// Just build the list from scratch
List<QtProjectVariable> variables = new CopyOnWriteArrayList<>();
try (Scanner scanner = new Scanner(document.get())) {
QtProjectVariable next;
while ((next = QtProjectVariable.findNextVariable(scanner)) != null) {
variables.add(next);
}
}
return variables;
}
/**
* Retrieves a specific Qt Project Variable from the provided <code>IDocument</code>. If the variable cannot be found,
* <code>null</code> is returned instead.
* <p>
* <b>Note:</b> This method is greedy in the sense that it returns the first match it finds. If multiple variables exist with
* the same name in the <code>IDocument</code>, this method will only return the first match.
* </p>
*
* @param name
* the name of the variable
* @return the <code>QtProjectVariable</code> or <code>null</code> if it couldn't be found
*/
public QtProjectVariable getVariable(String name) {
for (QtProjectVariable v : variables) {
if (v.getName().equals(name)) {
return v;
}
}
return null;
}
/**
* Returns a list of all Qt Project Variables found within the provided <code>IDocument</code>. A fresh list is always returned
* with the internal list copied into it. As such, modifying this list does not modify the internal list of the parser.
*
* @return the list of all Qt Project Variables
*/
public List<QtProjectVariable> getAllVariables() {
return new ArrayList<>(variables);
}
@Override
public void documentAboutToBeChanged(DocumentEvent event) {
// Nothing to do
}
@Override
public void documentChanged(DocumentEvent event) {
// Re-parse the document every time it changes
variables = parse();
}
@Override
protected void finalize() throws Throwable {
// Make sure that we are removed from the document's listeners
if (document != null) {
document.removeDocumentListener(this);
}
}
}