/** * This file Copyright (c) 2005-2008 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain other free and open source software ("FOSS") code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.editor.css.contentassist; import java.util.Arrays; import com.aptana.ide.editor.css.lexing.CSSTokenTypes; import com.aptana.ide.editor.css.parsing.CSSMimeType; import com.aptana.ide.lexer.Lexeme; import com.aptana.ide.lexer.LexemeList; /** * @author Robin Debreuil */ public final class CSSUtils { /** * Private constructor for utility class */ private CSSUtils() { } /** * Returns the "location" we are currently in. What this means in the end is that it helps us * figure out which of three states we are in. This also sets the current name hash (which * should be moved to CSSOffsetMapper eventually) * * @param offset * The current offset * @param lexemeList * @return One of the location enumerations */ public static String getLocation(int offset, LexemeList lexemeList) { if (offset == 0) { return CSSContentAssistProcessor.OUTSIDE_RULE; } String location = CSSContentAssistProcessor.OUTSIDE_RULE; int position = lexemeList.getLexemeFloorIndex(offset); boolean foundColon = false; // backtrack over lexemes to find name - we are really just // searching for the last OPEN_ELEMENT while (position >= 0) { Lexeme curLexeme = lexemeList.get(position); if (!curLexeme.getLanguage().equals(CSSMimeType.MimeType)) { break; } if (curLexeme.typeIndex == CSSTokenTypes.RCURLY) { location = CSSContentAssistProcessor.OUTSIDE_RULE; break; } if (curLexeme.typeIndex == CSSTokenTypes.COLON) { if (curLexeme.offset != offset) { foundColon = true; } } if (curLexeme.typeIndex == CSSTokenTypes.SEMICOLON || curLexeme.typeIndex == CSSTokenTypes.LCURLY) { if (offset != curLexeme.offset) { if (foundColon) { location = CSSContentAssistProcessor.ARG_ASSIST; } else { location = CSSContentAssistProcessor.INSIDE_RULE; } break; } } position--; } /* * if (currentHash.size() > 0) { lexemeHash = StringUtils.join(":", (String[]) currentHash * .toArray(new String[currentHash.size()])); // We add a trailing ":" as that indicates * we've finished typing // propertyName if (location.equals(ARG_ASSIST) && * lexemeHash.indexOf(":") < 0) lexemeHash += ":"; } else lexemeHash = ""; */ return location; } /** * We don't insert a : if there is already one there * * @param offset * @param ll * @return boolean */ public static boolean isColonAlreadyInserted(int offset, LexemeList ll) { Lexeme sibling = ll.getFloorLexeme(offset); Lexeme colon = getNextLexemeOfType(sibling, new int[] { CSSTokenTypes.COLON }, new int[] { CSSTokenTypes.SEMICOLON, CSSTokenTypes.RCURLY }, ll); return colon != null; } /** * getNextLexemeOfType * * @param startLexeme * @param lexemeTypes * @param lexemeList * @return Lexeme */ public static Lexeme getNextLexemeOfType(Lexeme startLexeme, int[] lexemeTypes, LexemeList lexemeList) { return getNextLexemeOfType(startLexeme, lexemeTypes, new int[0], lexemeList); } /** * getNextLexemeOfType * * @param startLexeme * @param lexemeTypes * @param lexemeTypesToBail * @param lexemeList * @return Lexeme */ public static Lexeme getNextLexemeOfType(Lexeme startLexeme, int[] lexemeTypes, int[] lexemeTypesToBail, LexemeList lexemeList) { Arrays.sort(lexemeTypes); Arrays.sort(lexemeTypesToBail); int index = lexemeList.getLexemeIndex(startLexeme); for (int i = index; i < lexemeList.size(); i++) { Lexeme l = lexemeList.get(i); if (Arrays.binarySearch(lexemeTypes, l.typeIndex) >= 0) { return l; } if (Arrays.binarySearch(lexemeTypesToBail, l.typeIndex) >= 0) { return null; } } return null; } }