/******************************************************************************* * Copyright (c) 2009 Red Hat, Inc. * 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: * Red Hat - initial API and implementation *******************************************************************************/ package org.eclipse.linuxtools.internal.valgrind.ui.editor; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.eclipse.jface.text.rules.ICharacterScanner; import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.IWordDetector; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.rules.WordRule; public class SuppressionKindRule implements IRule { private Map<String, List<String>> kinds; private IToken token; private WordRule subrule; private static final IToken DUMMY_TOKEN = new Token(null); private static final char[] COLON = new char[] { ':' }; public SuppressionKindRule(Map<String, List<String>> suppKinds, IToken successToken) { kinds = suppKinds; token = successToken; final List<String> suppKindsList = new ArrayList<>(); for (List<String> entry : suppKinds.values()) { suppKindsList.addAll(entry); } subrule = new WordRule(new IWordDetector() { @Override public boolean isWordStart(char c) { for (String kind : suppKindsList) { if (c == kind.charAt(0)) { return true; } } return false; } @Override public boolean isWordPart(char c) { return Character.isJavaIdentifierPart(c); } }); for (String kind : suppKindsList) { subrule.addWord(kind, DUMMY_TOKEN); } } @Override public IToken evaluate(ICharacterScanner scanner) { IToken result = subrule.evaluate(scanner); StringBuffer tool = new StringBuffer(); StringBuffer kind = new StringBuffer(); if (!result.isUndefined()) { boolean match = true; // move to beginning of token int tokenLength = ((SuppressionsElementScanner) scanner).getTokenLength(); for (int i = 0; i < tokenLength; i++) { scanner.unread(); } // check first char before token is a ':' match = checkColon(scanner); if (match) { // move to beginning of line int preTokenLength = 0; while (scanner.getColumn() > 0) { scanner.unread(); preTokenLength++; } // ensure any leading characters are whitespace boolean foundChar = false; while (preTokenLength-- > 1) { // skip colon int ch = scanner.read(); if (match && !Character.isWhitespace(ch)) { foundChar = true; tool.append(Character.toChars(ch)); } else if (foundChar) { // encountered whitespace after tool name started match = false; } } scanner.read(); // consume colon // reset to end of token for (int i = 0; i < tokenLength; i++) { int ch = scanner.read(); if (match) { kind.append(Character.toChars(ch)); } } // assert kind is valid for tool if (match) { List<String> kindList = kinds.get(tool.toString()); if (kindList == null || !kindList.contains(kind.toString())) { match = false; } } else { // reset to beginning of token unreadBuffer(scanner, tokenLength); } } if (!match) { result = Token.UNDEFINED; } else { result = token; } } return result; } private void unreadBuffer(ICharacterScanner scanner, int length) { for (int i = 0; i < length; i++) { scanner.unread(); } } private boolean checkColon(ICharacterScanner scanner) { if (scanner.getColumn() == 0) { // nothing to read return false; } scanner.unread(); int ch = scanner.read(); return Arrays.equals(Character.toChars(ch), COLON); } }