Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 194b930cbff21920d0ee9b4d97621fbb427f21dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*******************************************************************************
 * Copyright (c) 2007, 2012 Wind River Systems, Inc. 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:
 *    Markus Schorn (Wind River Systems)
 *    Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
 *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;

/**
 * Visitor to find macros in a BTree.
 * @since 4.0.2
 */
public final class MacroContainerCollector implements IBTreeVisitor {
	private final PDOMLinkage linkage;
	private final char[] matchChars;
	private final boolean prefixLookup;
	private final IContentAssistMatcher contentAssistMatcher;
	private final boolean caseSensitive;
	private IProgressMonitor monitor= null;
	private int monitorCheckCounter= 0;
	
	private List<PDOMMacroContainer> macros = new ArrayList<PDOMMacroContainer>();


	/**
	 * Collects all nodes with given name, passing the filter. If prefixLookup is set to
	 * <code>true</code> a binding is considered if its name starts with the given prefix.
	 * 
	 * @param linkage
	 * @param name
	 * @param prefixLookup
	 *            If set to <code>true</code> a binding is considered if its name starts with the given prefix
	 *            Otherwise, the binding will only be considered if its name matches exactly. This parameter
	 *            is ignored if <code>contentAssistLookup</code> is true.
	 * @param contentAssistLookup
	 *            If set to <code>true</code> a binding is considered if its names matches according to the
	 *            current content assist matching rules.
	 * @param caseSensitive
	 *            Ignored if <code>contentAssistLookup</code> is true.
	 */
	public MacroContainerCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup,
			boolean contentAssistLookup, boolean caseSensitive) {
		if (contentAssistLookup) {
			IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(name); 
			this.contentAssistMatcher =  matcher.matchRequiredAfterBinarySearch() ? matcher : null;
			this.matchChars = matcher.getPrefixForBinarySearch();
			this.prefixLookup= true;
			this.caseSensitive= false;
		} else {
			this.contentAssistMatcher = null;
			this.matchChars = name;
			this.prefixLookup= prefixLookup;
			this.caseSensitive= caseSensitive;
		}
		this.linkage= linkage;
	}
	
	/**
	 * Allows to cancel a visit. If set a visit may throw an OperationCancelledException.
	 * @since 4.0
	 */
	public void setMonitor(IProgressMonitor pm) {
		monitor= pm;
	}
	
	@Override
	final public int compare(long record) throws CoreException {
		if (monitor != null)
			checkCancelled();
		IString rhsName= PDOMNamedNode.getDBName(linkage.getDB(), record);
		return compare(rhsName);
	}

	private int compare(IString rhsName) throws CoreException {
		int cmp;
		if (prefixLookup) {
			cmp= rhsName.comparePrefix(matchChars, false);
			if(caseSensitive) {
				cmp= cmp==0 ? rhsName.comparePrefix(matchChars, true) : cmp;
			}
		} else {
			if(caseSensitive) {
				cmp= rhsName.compareCompatibleWithIgnoreCase(matchChars);
			}
			else {
				cmp= rhsName.compare(matchChars, false);
			}
		}
		return cmp;
	}
	
	@Override
	final public boolean visit(long record) throws CoreException {
		if (monitor != null)
			checkCancelled();

		if (record == 0)
			return true;

		if (contentAssistMatcher != null) {
			char[] nodeName = PDOMNamedNode.getDBName(linkage.getDB(), record).getChars();
			if (contentAssistMatcher.match(nodeName)) {
				macros.add(new PDOMMacroContainer(linkage, record));
			}
		} else { 
			macros.add(new PDOMMacroContainer(linkage, record));
		}

		return true; // look for more
	}
	
	final public List<PDOMMacroContainer> getMacroList() {
		return macros;
	}
	
	private void checkCancelled() {
		if (++monitorCheckCounter % 0x1000 == 0 && monitor.isCanceled()) {
			throw new OperationCanceledException();
		}
	}
}

Back to the top