/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.tools.core.utilities.general; import com.google.dart.compiler.parser.Token; import java.util.Arrays; import java.util.List; /** * The class <code>SourceUtilities</code> defines utility methods for processing strings. * * @coverage dart.tools.core.utilities */ public final class SourceUtilities { /** * The line separator used on the current platform. */ public static final String LINE_SEPARATOR = System.getProperty("line.separator"); /** * The token representing a #library directive. */ public static String LIBRARY_DIRECTIVE = Token.LIBRARY.getSyntax(); /** * The token representing an #import directive. */ public static String IMPORT_DIRECTIVE = Token.IMPORT.getSyntax(); /** * The token representing a #source directive. */ public static String SOURCE_DIRECTIVE = Token.SOURCE.getSyntax(); /** * The token representing a #resource directive. */ public static String RESOURCE_DIRECTIVE = Token.RESOURCE.getSyntax(); /** * The token representing a #native directive. */ public static String NATIVE_DIRECTIVE = Token.NATIVE.getSyntax(); /** * A list containing all of the directives in the order in which they must appear in a valid * source file. */ private static List<String> DIRECTIVES = Arrays.asList( LIBRARY_DIRECTIVE, IMPORT_DIRECTIVE, SOURCE_DIRECTIVE, RESOURCE_DIRECTIVE, NATIVE_DIRECTIVE); /** * Return the offset into the given compilation unit contents at which a directive with the given * name and a literal value equal to the given relative path should be added. The offset will * always be the index of the first character after an end-of-line marker. * * @param contents the contents of the compilation unit to which the directive will be added * @param directiveName the name of the directive (including the leading pound sign) * @param relativePath the path of the file referenced in the literal string in the directive * @return the index at which the text for the new directive should be inserted */ public static int findInsertionPointForSource(String contents, String directiveName, String relativePath) { // TODO(brianwilkerson) Improve the algorithm used to find the location for the directive. If // the directives in the unit are in the right order and at the beginning of the file, this // should work fine. If not, this can produce additional compilation errors. int index = DIRECTIVES.indexOf(directiveName); if (index < 0) { throw new IllegalArgumentException("Unrecognized directive name: " + directiveName); } int directiveCount = DIRECTIVES.size(); for (int i = index; i >= 0; i--) { int offset = contents.lastIndexOf(DIRECTIVES.get(i)); if (offset >= 0) { return SourceUtilities.findStartOfNextLine(contents, offset); } } for (int i = index + 1; i < directiveCount; i++) { int offset = contents.indexOf(DIRECTIVES.get(i)); if (offset >= 0) { return SourceUtilities.findStartOfLine(contents, offset); } } return 0; } /** * Return the index of the first character in the given string after the first end-of-line marker * before the given start index. If there is no end-of-line marker before the given index, return * zero (0). * * @param string the string being searched * @param startIndex the index at which the search is to begin * @return the index of the first character in the given string after the first end-of-line marker * before the given start index */ public static int findStartOfLine(String string, int startIndex) { int index = startIndex; while (index >= 0) { if (string.charAt(index) == '\r' || string.charAt(index) == '\n') { return index + 1; } index = index + 1; } return 0; } /** * Return the index of the first character in the given string after the first end-of-line marker * at or after the given index. If there is no end-of-line marker at or after the given index, or * if there are no characters after the next end-of-line marker, return the length of the string. * * @param string the string being searched * @param startIndex the index at which the search is to begin * @return the index of the first character in the given string after the first end-of-line marker * at or after the given index */ public static int findStartOfNextLine(String string, int startIndex) { int length = string.length(); int index = startIndex; while (index < length) { if (string.charAt(index) == '\r') { if (index + 1 < length && string.charAt(index + 1) == '\n') { return index + 2; } return index + 1; } else if (string.charAt(index) == '\n') { return index + 1; } index = index + 1; } return length; } /** * Prevent the creation of instances of this class. */ private SourceUtilities() { super(); } }