|
From: Christopher W. <caw...@us...> - 2006-03-25 02:27:41
|
Update of /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6145/src/org/rubypeople/rdt/internal/core/util Modified Files: Util.java CharOperation.java Added Files: SimpleWordSet.java Log Message: my initial working version of a Ruby Browsing Perspective Index: CharOperation.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/CharOperation.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** CharOperation.java 13 Dec 2005 19:59:47 -0000 1.3 --- CharOperation.java 25 Mar 2006 02:27:35 -0000 1.4 *************** *** 19,36 **** * * <pre> - * * * * * ! * toBeFound = 'c' ! * array = { ' a', 'b', 'c', 'd' } ! * start = 2 [...1245 lines suppressed...] ! * the array for which a hashcode is required ! * @return the hashcode ! * @throws NullPointerException ! * if array is null ! */ ! public static final int hashCode(char[] array) { ! int length = array.length; ! int hash = length == 0 ? 31 : array[0]; ! if (length < 8) { ! for (int i = length; --i > 0;) ! hash = (hash * 31) + array[i]; ! } else { ! // 8 characters is enough to compute a decent hash code, don't waste ! // time examining every character ! for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2) ! hash = (hash * 31) + array[i]; ! } ! return hash & 0x7FFFFFFF; ! } } --- NEW FILE: SimpleWordSet.java --- /******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.core.util; public final class SimpleWordSet { // to avoid using Enumerations, walk the individual values skipping nulls public char[][] words; public int elementSize; // number of elements in the table public int threshold; public SimpleWordSet(int size) { this.elementSize = 0; this.threshold = size; // size represents the expected number of elements int extraRoom = (int) (size * 1.5f); if (this.threshold == extraRoom) extraRoom++; this.words = new char[extraRoom][]; } public char[] add(char[] word) { int length = this.words.length; int index = CharOperation.hashCode(word) % length; char[] current; while ((current = words[index]) != null) { if (CharOperation.equals(current, word)) return current; if (++index == length) index = 0; } words[index] = word; // assumes the threshold is never equal to the size of the table if (++elementSize > threshold) rehash(); return word; } public boolean includes(char[] word) { int length = this.words.length; int index = CharOperation.hashCode(word) % length; char[] current; while ((current = words[index]) != null) { if (CharOperation.equals(current, word)) return true; if (++index == length) index = 0; } return false; } private void rehash() { SimpleWordSet newSet = new SimpleWordSet(elementSize * 2); // double the number of expected elements char[] current; for (int i = words.length; --i >= 0;) if ((current = words[i]) != null) newSet.add(current); this.words = newSet.words; this.elementSize = newSet.elementSize; this.threshold = newSet.threshold; } } Index: Util.java =================================================================== RCS file: /cvsroot/rubyeclipse/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/util/Util.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** Util.java 22 Feb 2006 20:04:04 -0000 1.7 --- Util.java 25 Mar 2006 02:27:35 -0000 1.8 *************** *** 5,8 **** --- 5,12 ---- package org.rubypeople.rdt.internal.core.util; + import java.io.BufferedInputStream; + import java.io.IOException; + import java.io.InputStream; + import java.io.InputStreamReader; import java.io.PrintStream; import java.util.Locale; *************** *** 10,18 **** --- 14,27 ---- import java.util.ResourceBundle; + import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; + import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; + import org.eclipse.core.runtime.content.IContentType; import org.rubypeople.rdt.core.IRubyElement; + import org.rubypeople.rdt.core.IRubyModelStatusConstants; import org.rubypeople.rdt.core.RubyConventions; import org.rubypeople.rdt.core.RubyCore; *************** *** 27,30 **** --- 36,41 ---- /* Bundle containing messages */ protected static ResourceBundle bundle; + private static boolean ENABLE_RUBY_LIKE_EXTENSIONS = true; + private static char[][] RUBY_LIKE_EXTENSIONS; private final static String bundleName = "org.rubypeople.rdt.internal.core.util.messages"; //$NON-NLS-1$ *************** *** 328,332 **** switch (elementType) { case IRubyElement.RUBY_MODEL: ! case IRubyElement.PROJECT: return false; case IRubyElement.SCRIPT: --- 339,343 ---- switch (elementType) { case IRubyElement.RUBY_MODEL: ! case IRubyElement.RUBY_PROJECT: return false; case IRubyElement.SCRIPT: *************** *** 343,347 **** --- 354,545 ---- } } + + /** + * Returns the substring of the given file name, ending at the start of a + * Ruby like extension. The entire file name is returned if it doesn't end + * with a Ruby like extension. + */ + public static String getNameWithoutRubyLikeExtension(String fileName) { + int index = indexOfRubyLikeExtension(fileName); + if (index == -1) + return fileName; + return fileName.substring(0, index); + } + + /* + * Returns the index of the Java like extension of the given file name + * or -1 if it doesn't end with a known Java like extension. + * Note this is the index of the '.' even if it is not considered part of the extension. + */ + public static int indexOfRubyLikeExtension(String fileName) { + int fileNameLength = fileName.length(); + char[][] javaLikeExtensions = getRubyLikeExtensions(); + extensions: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) { + char[] extension = javaLikeExtensions[i]; + int extensionLength = extension.length; + int extensionStart = fileNameLength - extensionLength; + int dotIndex = extensionStart - 1; + if (dotIndex < 0) continue; + if (fileName.charAt(dotIndex) != '.') continue; + for (int j = 0; j < extensionLength; j++) { + if (fileName.charAt(extensionStart + j) != extension[j]) + continue extensions; + } + return dotIndex; + } + return -1; + } + + /** + * Returns the registered Ruby like extensions. + */ + public static char[][] getRubyLikeExtensions() { + if (RUBY_LIKE_EXTENSIONS == null) { + // TODO (jerome) reenable once RDT UI supports other file extensions (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=71460) + if (!ENABLE_RUBY_LIKE_EXTENSIONS) + RUBY_LIKE_EXTENSIONS = new char[][] {"rb".toCharArray()}; + else { + IContentType javaContentType = Platform.getContentTypeManager().getContentType(RubyCore.RUBY_SOURCE_CONTENT_TYPE); + String[] fileExtensions = javaContentType == null ? null : javaContentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC); + // note that file extensions contains "java" as it is defined in JDT Core's plugin.xml + int length = fileExtensions == null ? 0 : fileExtensions.length; + char[][] extensions = new char[length][]; + SimpleWordSet knownExtensions = new SimpleWordSet(length); // used to ensure no duplicate extensions + extensions[0] = "rb".toCharArray(); // ensure that "rb" is first + knownExtensions.add(extensions[0]); + int index = 1; + for (int i = 0; i < length; i++) { + String fileExtension = fileExtensions[i]; + char[] extension = fileExtension.toCharArray(); + if (!knownExtensions.includes(extension)) { + extensions[index++] = extension; + knownExtensions.add(extension); + } + } + if (index != length) + System.arraycopy(extensions, 0, extensions = new char[index][], 0, index); + RUBY_LIKE_EXTENSIONS = extensions; + } + } + return RUBY_LIKE_EXTENSIONS; + } + + private static final int DEFAULT_READING_SIZE = 8192; + + /** + * @param file + * @return + * @throws IOException + * @throws CoreException + */ + public static char[] getResourceContentsAsCharArray(IFile file) throws RubyModelException { + // Get encoding from file + String encoding = null; + try { + encoding = file.getCharset(); + } catch (CoreException ce) { + // do not use any encoding + } + return getResourceContentsAsCharArray(file, encoding); + } + + public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws RubyModelException { + // Get resource contents + InputStream stream = null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new RubyModelException(e, IRubyModelStatusConstants.ELEMENT_DOES_NOT_EXIST); + } + try { + return Util.getInputStreamAsCharArray(stream, -1, encoding); + } catch (IOException e) { + throw new RubyModelException(e, IRubyModelStatusConstants.IO_EXCEPTION); + } finally { + try { + stream.close(); + } catch (IOException e) { + // ignore + } + } + } + + /** + * Returns the given input stream's contents as a character array. If a + * length is specified (ie. if length != -1), only length chars are + * returned. Otherwise all chars in the stream are returned. Note this + * doesn't close the stream. + * + * @throws IOException + * if a problem occured reading the stream. + */ + public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException { + InputStreamReader reader = null; + reader = encoding == null ? new InputStreamReader(stream) : new InputStreamReader(stream, encoding); + char[] contents; + if (length == -1) { + contents = new char[0]; + int contentsLength = 0; + int amountRead = -1; + do { + int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read + // at + // least + // 8K + + // resize contents if needed + if (contentsLength + amountRequested > contents.length) { + System.arraycopy(contents, 0, contents = new char[contentsLength + amountRequested], 0, contentsLength); + } + + // read as many chars as possible + amountRead = reader.read(contents, contentsLength, amountRequested); + + if (amountRead > 0) { + // remember length of contents + contentsLength += amountRead; + } + } while (amountRead != -1); + + // Do not keep first character for UTF-8 BOM encoding + int start = 0; + if (contentsLength > 0 && "UTF-8".equals(encoding)) { //$NON-NLS-1$ + if (contents[0] == 0xFEFF) { // if BOM char then skip + contentsLength--; + start = 1; + } + } + // resize contents if necessary + if (contentsLength < contents.length) { + System.arraycopy(contents, start, contents = new char[contentsLength], 0, contentsLength); + } + } else { + contents = new char[length]; + int len = 0; + int readSize = 0; + while ((readSize != -1) && (len != length)) { + // See PR 1FMS89U + // We record first the read size. In this case len is the actual + // read size. + len += readSize; + readSize = reader.read(contents, len, length - len); + } + // Do not keep first character for UTF-8 BOM encoding + int start = 0; + if (length > 0 && "UTF-8".equals(encoding)) { //$NON-NLS-1$ + if (contents[0] == 0xFEFF) { // if BOM char then skip + len--; + start = 1; + } + } + // See PR 1FMS89U + // Now we need to resize in case the default encoding used more than + // one byte for each + // character + if (len != length) System.arraycopy(contents, start, (contents = new char[len]), 0, len); + } + return contents; + } } |