/* * Copyright (c) 2013, 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.engine.services.refactoring; import com.google.dart.engine.element.Element; import com.google.dart.engine.services.status.RefactoringStatus; import com.google.dart.engine.services.status.RefactoringStatusSeverity; import org.apache.commons.lang3.StringUtils; import java.text.MessageFormat; /** * Provides methods for checking {@link Element} naming conventions. */ public final class NamingConventions { /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularAttributeName(String name) { return validateTagOrAttributeName(name, "Attribute name"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularComponentName(String name) { return validateLowerCamelCase(name, "Component"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularControllerName(String name) { return validateLowerCamelCase(name, "Controller"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularFormatterName(String name) { return validateLowerCamelCase(name, "Formatter"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularPropertyName(String name) { return validateTagOrAttributeName(name, "Property name"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularScopePropertyName(String name) { return validateLowerCamelCase(name, "Scope property"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateAngularTagSelectorName(String name) { return validateTagOrAttributeName(name, "Tag selector name"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateClassName(String name) { return validateUpperCamelCase(name, "Class"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateConstructorName(String name) { if (name != null && name.isEmpty()) { return new RefactoringStatus(); } return validateLowerCamelCase(name, "Constructor"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateFieldName(String name) { return validateLowerCamelCase(name, "Field"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateFunctionName(String name) { return validateLowerCamelCase(name, "Function"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateFunctionTypeAliasName(String name) { return validateUpperCamelCase(name, "Function type alias"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateImportPrefixName(String name) { if (name != null && name.isEmpty()) { return new RefactoringStatus(); } return validateLowerCamelCase(name, "Import prefix"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateLibraryName(String name) { // null if (name == null) { return RefactoringStatus.createErrorStatus("Library name must not be null."); } // blank if (StringUtils.isBlank(name)) { return RefactoringStatus.createErrorStatus("Library name must not be blank."); } // check identifiers String[] identifiers = StringUtils.splitPreserveAllTokens(name, '.'); for (String identifier : identifiers) { RefactoringStatus status = validateIdentifier0(identifier, "Library name identifier"); if (!status.isOK()) { return status; } } // should not have upper-case letters for (String identifier : identifiers) { char[] chars = identifier.toCharArray(); for (char c : chars) { if (Character.isUpperCase(c)) { return RefactoringStatus.createWarningStatus("Library name should consist of lower-case identifier separated by dots."); } } } // OK return new RefactoringStatus(); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateMethodName(String name) { return validateLowerCamelCase(name, "Method"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateParameterName(String name) { return validateLowerCamelCase(name, "Parameter"); } /** * @return the {@link RefactoringStatus} with {@link RefactoringStatusSeverity#OK} if the name is * valid, {@link RefactoringStatusSeverity#WARNING} if the name is discouraged, or * {@link RefactoringStatusSeverity#ERROR} if the name is illegal. */ public static RefactoringStatus validateVariableName(String name) { return validateLowerCamelCase(name, "Variable"); } private static RefactoringStatus validateIdentifier(String identifier, String elementName) { return validateIdentifier0(identifier, elementName + " name"); } private static RefactoringStatus validateIdentifier0(String identifier, String identifierName) { // has leading/trailing spaces String trimmed = identifier.trim(); if (!identifier.equals(trimmed)) { String message = MessageFormat.format( "{0} must not start or end with a blank.", identifierName); return RefactoringStatus.createErrorStatus(message); } // empty int length = identifier.length(); if (length == 0) { String message = MessageFormat.format("{0} must not be empty.", identifierName); return RefactoringStatus.createErrorStatus(message); } char currentChar = identifier.charAt(0); if (!Character.isLetter(currentChar) && currentChar != '_' && currentChar != '$') { String message = MessageFormat.format( "{0} must not start with ''{1}''.", identifierName, currentChar); return RefactoringStatus.createErrorStatus(message); } for (int i = 1; i < length; i++) { currentChar = identifier.charAt(i); if (!Character.isLetterOrDigit(currentChar) && currentChar != '_' && currentChar != '$') { String message = MessageFormat.format( "{0} must not contain ''{1}''.", identifierName, currentChar); return RefactoringStatus.createErrorStatus(message); } } return new RefactoringStatus(); } /** * Validate the given identifier, which should be lower camel case. */ private static RefactoringStatus validateLowerCamelCase(String identifier, String elementName) { // null if (identifier == null) { String message = MessageFormat.format("{0} name must not be null.", elementName); return RefactoringStatus.createErrorStatus(message); } // is not identifier RefactoringStatus status = validateIdentifier(identifier, elementName); if (!status.isOK()) { return status; } // is private, OK if (identifier.charAt(0) == '_') { return new RefactoringStatus(); } // leading $, OK if (identifier.charAt(0) == '$') { return new RefactoringStatus(); } // does not start with lower case if (!Character.isLowerCase(identifier.charAt(0))) { String message = MessageFormat.format( "{0} name should start with a lowercase letter.", elementName); return RefactoringStatus.createWarningStatus(message); } // OK return new RefactoringStatus(); } private static RefactoringStatus validateTagOrAttributeName(String name, String elementName) { // null if (name == null) { return RefactoringStatus.createErrorStatus(elementName + " must not be null."); } // blank if (StringUtils.isBlank(name)) { return RefactoringStatus.createErrorStatus(elementName + " must not be blank."); } // first character char currentChar = name.charAt(0); if (!Character.isLetter(currentChar)) { String message = MessageFormat.format( elementName + " must not start with ''{0}''.", currentChar); return RefactoringStatus.createErrorStatus(message); } // second+ character for (int i = 1; i < name.length(); i++) { currentChar = name.charAt(i); if (!Character.isLetterOrDigit(currentChar) && currentChar != '-') { String message = MessageFormat.format( elementName + " must not contain ''{0}''.", currentChar); return RefactoringStatus.createErrorStatus(message); } } // OK return new RefactoringStatus(); } /** * Validate the given identifier, which should be upper camel case. */ private static RefactoringStatus validateUpperCamelCase(String identifier, String elementName) { // null if (identifier == null) { String message = MessageFormat.format("{0} name must not be null.", elementName); return RefactoringStatus.createErrorStatus(message); } // is not identifier RefactoringStatus status = validateIdentifier(identifier, elementName); if (!status.isOK()) { return status; } // is private, OK if (identifier.charAt(0) == '_') { return new RefactoringStatus(); } // leading $, OK if (identifier.charAt(0) == '$') { return new RefactoringStatus(); } // does not start with upper case if (!Character.isUpperCase(identifier.charAt(0))) { // By convention, class names usually start with an uppercase letter String message = MessageFormat.format( "{0} name should start with an uppercase letter.", elementName); return RefactoringStatus.createWarningStatus(message); } // OK return new RefactoringStatus(); } private NamingConventions() { } }