/** * */ package org.rubypeople.rdt.core; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.rubypeople.rdt.internal.core.LoadpathEntry; import org.rubypeople.rdt.internal.core.RubyModelStatus; import org.rubypeople.rdt.internal.core.util.Messages; /** * @author Chris * */ public class RubyConventions { /** * Validate the given ruby script name. A ruby script name must obey the * following rules: * <ul> * <li> it must not be null * <li> it must match the exact filename or file extensions for the ruby content type * <li> its prefix must be a valid identifier * <li> it must not contain any characters or substrings that are not valid * on the file system on which workspace root is located. * </ul> * </p> * * @param name * the name of a ruby script * @return a status object with code <code>IStatus.OK</code> if the given * name is valid as a ruby script name, otherwise a status object * indicating what is wrong with the name */ public static IStatus validateRubyScriptName(String name) { if (name == null) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_unit_nullName), null); } if (!org.rubypeople.rdt.internal.core.util.Util.isRubyLikeFileName(name)) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_unit_notRubyName), null); } IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE); if (!status.isOK()) { return status; } return RubyModelStatus.VERIFIED_OK; } /** * Validate the given Ruby identifier. The identifier must not have the same * spelling as a Ruby keyword, boolean literal (<code>"true"</code>, * <code>"false"</code>), or null literal (<code>"null"</code>). * A valid identifier can act as a simple type name, method name or * field name. * * @param id * the Ruby identifier * @return a status object with code <code>IStatus.OK</code> if the given * identifier is a valid Ruby identifier, otherwise a status object * indicating what is wrong with the identifier */ public static IStatus validateIdentifier(String id) { // if (scannedIdentifier(id) != null) { // FIXME We should actually check the identifier return RubyModelStatus.VERIFIED_OK; // } else { // return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, // Util.bind("convention.illegalIdentifier", id), null); //$NON-NLS-1$ // } } public static IStatus validateRubyTypeName(String typeName) { if (typeName == null) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null); } if (typeName.length() == 0) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_type_invalidName, typeName), null); } if (!isConstant(typeName)) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, "Class name must be a constant. It must begin with a capital letter, and contain only letters, digits, or underscores.", null); } return RubyModelStatus.VERIFIED_OK; } public static IStatus validateConstant(String constantName) { if (constantName == null) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null); } if (constantName.length() == 0) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_type_invalidName, constantName), null); } if (!isConstant(constantName)) { return new Status(IStatus.ERROR, RubyCore.PLUGIN_ID, -1, "Name must be a constant. It must begin with a capital letter, and contain only letters, digits, or underscores.", null); } return RubyModelStatus.VERIFIED_OK; } private static boolean isConstant(String className) { if (className == null || className.length() == 0) return false; if (!Character.isLowerCase(className.charAt(0)) && !Character.isLetter(className.charAt(0))) return false; int namespaceDelimeterIndex = className.indexOf("::"); if (namespaceDelimeterIndex != -1) { return isConstant(className.substring(0, namespaceDelimeterIndex)) && isConstant(className.substring(namespaceDelimeterIndex+2)); } for (int i = 0; i < className.length(); i++) { char c = className.charAt(i); if (!Character.isLetterOrDigit(c) && c != '_') return false; } return true; } public static IStatus validateSourceFolderName(String packName) { // TODO Actually do some validation return RubyModelStatus.VERIFIED_OK; } public static IRubyModelStatus validateLoadpath(IRubyProject rubyProject, ILoadpathEntry[] rawCLoadpath, IPath projectOutputLocation) { return LoadpathEntry.validateLoadpath(rubyProject, rawCLoadpath, projectOutputLocation); } public static IStatus validateMethodName(String methodName) { return validateIdentifier(methodName); } /** * Retruns true if character can be part of an identifier (including symbol, instance, class and global variable beginnings. * @param c * @return */ public static boolean isRubyIdentifierPart(char c) { return isStrictRubyIdentifierPart(c) || c == ':' || c == '$' || c == '@' || c =='!' || c == '?'; } /** * Retruns true if the character is ok as part of the strictly idnetifier portion of a variable/method name (i.e. don't count $, @, ?, !) * @param c * @return */ private static boolean isStrictRubyIdentifierPart(char c) { return Character.isLetterOrDigit(c) || c == '_'; } }