/******************************************************************************* * Copyright (c) 2000, 2008 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.eclipse.wst.jsdt.internal.core; import java.util.Map; import org.eclipse.wst.jsdt.core.Flags; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.compiler.InvalidInputException; import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistOptions; import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions; import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner; import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper; import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens; public class InternalNamingConventions { private static final char[] DEFAULT_NAME = "name".toCharArray(); //$NON-NLS-1$ private static Scanner getNameScanner(CompilerOptions compilerOptions) { return new Scanner( false /*comment*/, false /*whitespace*/, false /*nls*/, compilerOptions.sourceLevel /*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); } public static void suggestArgumentNames(IJavaScriptProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[] internalPrefix, char[][] excludedNames, INamingRequestor requestor) { Map options = javaProject.getOptions(true); CompilerOptions compilerOptions = new CompilerOptions(options); AssistOptions assistOptions = new AssistOptions(options); suggestNames( packageName, qualifiedTypeName, dim, internalPrefix, assistOptions.argumentPrefixes, assistOptions.argumentSuffixes, excludedNames, getNameScanner(compilerOptions), requestor); } public static void suggestFieldNames(IJavaScriptProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, int modifiers, char[] internalPrefix, char[][] excludedNames, INamingRequestor requestor) { boolean isStatic = Flags.isStatic(modifiers); Map options = javaProject.getOptions(true); CompilerOptions compilerOptions = new CompilerOptions(options); AssistOptions assistOptions = new AssistOptions(options); suggestNames( packageName, qualifiedTypeName, dim, internalPrefix, isStatic ? assistOptions.staticFieldPrefixes : assistOptions.fieldPrefixes, isStatic ? assistOptions.staticFieldSuffixes : assistOptions.fieldSuffixes, excludedNames, getNameScanner(compilerOptions), requestor); } public static void suggestLocalVariableNames(IJavaScriptProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[] internalPrefix, char[][] excludedNames, INamingRequestor requestor) { Map options = javaProject.getOptions(true); CompilerOptions compilerOptions = new CompilerOptions(options); AssistOptions assistOptions = new AssistOptions(options); suggestNames( packageName, qualifiedTypeName, dim, internalPrefix, assistOptions.localPrefixes, assistOptions.localSuffixes, excludedNames, getNameScanner(compilerOptions), requestor); } private static void suggestNames( char[] packageName, char[] qualifiedTypeName, int dim, char[] internalPrefix, char[][] prefixes, char[][] suffixes, char[][] excludedNames, Scanner nameScanner, INamingRequestor requestor){ if(qualifiedTypeName == null || qualifiedTypeName.length == 0) return; if(internalPrefix == null) { internalPrefix = CharOperation.NO_CHAR; } else { internalPrefix = removePrefix(internalPrefix, prefixes); } char[] typeName = (qualifiedTypeName!=null)? CharOperation.lastSegment(qualifiedTypeName, '.'):null; if(prefixes == null || prefixes.length == 0) { prefixes = new char[1][0]; } else { int length = prefixes.length; System.arraycopy(prefixes, 0, prefixes = new char[length+1][], 0, length); prefixes[length] = CharOperation.NO_CHAR; } if(suffixes == null || suffixes.length == 0) { suffixes = new char[1][0]; } else { int length = suffixes.length; System.arraycopy(suffixes, 0, suffixes = new char[length+1][], 0, length); suffixes[length] = CharOperation.NO_CHAR; } char[][] tempNames = null; // compute variable name for base type try{ nameScanner.setSource(typeName); switch (nameScanner.getNextToken()) { case TerminalTokens.TokenNameint : case TerminalTokens.TokenNamebyte : case TerminalTokens.TokenNameshort : case TerminalTokens.TokenNamechar : case TerminalTokens.TokenNamelong : case TerminalTokens.TokenNamefloat : case TerminalTokens.TokenNamedouble : case TerminalTokens.TokenNameboolean : if (internalPrefix != null && internalPrefix.length > 0) return; char[] name = computeBaseTypeNames(typeName[0], excludedNames); if(name != null) { tempNames = new char[][]{name}; } break; } } catch(InvalidInputException e){ // ignore } // compute variable name for non base type if(tempNames == null) { tempNames = computeNames(typeName); } boolean acceptDefaultName = true; next : for (int i = 0; i < tempNames.length; i++) { char[] tempName = tempNames[i]; if(dim > 0) { int length = tempName.length; if (tempName[length-1] == 's'){ if(tempName.length > 1 && tempName[length-2] == 's') { System.arraycopy(tempName, 0, tempName = new char[length + 2], 0, length); tempName[length] = 'e'; tempName[length+1] = 's'; } } else if(tempName[length-1] == 'y') { System.arraycopy(tempName, 0, tempName = new char[length + 2], 0, length); tempName[length-1] = 'i'; tempName[length] = 'e'; tempName[length+1] = 's'; } else { System.arraycopy(tempName, 0, tempName = new char[length + 1], 0, length); tempName[length] = 's'; } } char[] unprefixedName = tempName; for (int j = 0; j <= internalPrefix.length; j++) { if(j == internalPrefix.length || CharOperation.prefixEquals(CharOperation.subarray(internalPrefix, j, -1), unprefixedName, false)) { tempName = CharOperation.concat(CharOperation.subarray(internalPrefix, 0, j), unprefixedName); if(j != 0) tempName[j] = ScannerHelper.toUpperCase(tempName[j]); for (int k = 0; k < prefixes.length; k++) { if(prefixes[k].length > 0 && ScannerHelper.isLetterOrDigit(prefixes[k][prefixes[k].length - 1])) { tempName[0] = ScannerHelper.toUpperCase(tempName[0]); } else { tempName[0] = ScannerHelper.toLowerCase(tempName[0]); } char[] prefixName = CharOperation.concat(prefixes[k], tempName); for (int l = 0; l < suffixes.length; l++) { char[] suffixName = CharOperation.concat(prefixName, suffixes[l]); suffixName = excludeNames( suffixName, prefixName, suffixes[l], excludedNames); try{ nameScanner.setSource(suffixName); switch (nameScanner.getNextToken()) { case TerminalTokens.TokenNameIdentifier : int token = nameScanner.getNextToken(); if (token == TerminalTokens.TokenNameEOF && nameScanner.startPosition == suffixName.length) { acceptName(suffixName, prefixes[k], suffixes[l], k == 0, l == 0, internalPrefix.length - j, requestor); acceptDefaultName = false; } break; default: suffixName = CharOperation.concat( prefixName, String.valueOf(1).toCharArray(), suffixes[l] ); suffixName = excludeNames( suffixName, prefixName, suffixes[l], excludedNames); nameScanner.setSource(suffixName); switch (nameScanner.getNextToken()) { case TerminalTokens.TokenNameIdentifier : token = nameScanner.getNextToken(); if (token == TerminalTokens.TokenNameEOF && nameScanner.startPosition == suffixName.length) { acceptName(suffixName, prefixes[k], suffixes[l], k == 0, l == 0, internalPrefix.length - j, requestor); acceptDefaultName = false; } } } } catch(InvalidInputException e){ // ignore } } } continue next; } } } // if no names were found if(acceptDefaultName) { char[] name = excludeNames(DEFAULT_NAME, DEFAULT_NAME, CharOperation.NO_CHAR, excludedNames); requestor.acceptNameWithoutPrefixAndSuffix(name, 0); } } private static void acceptName( char[] name, char[] prefix, char[] suffix, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters, INamingRequestor requestor) { if(prefix.length > 0 && suffix.length > 0) { requestor.acceptNameWithPrefixAndSuffix(name, isFirstPrefix, isFirstSuffix, reusedCharacters); } else if(prefix.length > 0){ requestor.acceptNameWithPrefix(name, isFirstPrefix, reusedCharacters); } else if(suffix.length > 0){ requestor.acceptNameWithSuffix(name, isFirstSuffix, reusedCharacters); } else { requestor.acceptNameWithoutPrefixAndSuffix(name, reusedCharacters); } } private static char[] computeBaseTypeNames(char firstName, char[][] excludedNames){ char[] name = new char[]{firstName}; for(int i = 0 ; i < excludedNames.length ; i++){ if(CharOperation.equals(name, excludedNames[i], false)) { name[0]++; if(name[0] > 'z') name[0] = 'a'; if(name[0] == firstName) return null; i = 0; } } return name; } private static char[][] computeNames(char[] sourceName){ char[][] names = new char[5][]; int nameCount = 0; boolean previousIsUpperCase = false; boolean previousIsLetter = true; for(int i = sourceName.length - 1 ; i >= 0 ; i--){ boolean isUpperCase = ScannerHelper.isUpperCase(sourceName[i]); boolean isLetter = ScannerHelper.isLetter(sourceName[i]); if(isUpperCase && !previousIsUpperCase && previousIsLetter){ char[] name = CharOperation.subarray(sourceName,i,sourceName.length); if(name.length > 1){ if(nameCount == names.length) { System.arraycopy(names, 0, names = new char[nameCount * 2][], 0, nameCount); } name[0] = ScannerHelper.toLowerCase(name[0]); names[nameCount++] = name; } } previousIsUpperCase = isUpperCase; previousIsLetter = isLetter; } if(nameCount == 0){ names[nameCount++] = CharOperation.toLowerCase(sourceName); } System.arraycopy(names, 0, names = new char[nameCount][], 0, nameCount); return names; } private static char[] excludeNames( char[] suffixName, char[] prefixName, char[] suffix, char[][] excludedNames) { int count = 2; int m = 0; while (m < excludedNames.length) { if(CharOperation.equals(suffixName, excludedNames[m], false)) { suffixName = CharOperation.concat( prefixName, String.valueOf(count++).toCharArray(), suffix ); m = 0; } else { m++; } } return suffixName; } private static char[] removePrefix(char[] name, char[][] prefixes) { // remove longer prefix char[] withoutPrefixName = name; if (prefixes != null) { int bestLength = 0; int nameLength = name.length; for (int i= 0; i < prefixes.length; i++) { char[] prefix = prefixes[i]; int prefixLength = prefix.length; if(prefixLength <= nameLength) { if(CharOperation.prefixEquals(prefix, name, false)) { if (prefixLength > bestLength) { bestLength = prefixLength; } } } else { int currLen = 0; for (; currLen < nameLength; currLen++) { if(ScannerHelper.toLowerCase(prefix[currLen]) != ScannerHelper.toLowerCase(name[currLen])) { if (currLen > bestLength) { bestLength = currLen; } break; } } if(currLen == nameLength && currLen > bestLength) { bestLength = currLen; } } } if(bestLength > 0) { if(bestLength == nameLength) { withoutPrefixName = CharOperation.NO_CHAR; } else { withoutPrefixName = CharOperation.subarray(name, bestLength, nameLength); } } } // // // // remove longer prefix // char[] withoutPrefixName = name; // if (prefixes != null) { // int bestLength = 0; // for (int i= 0; i < prefixes.length; i++) { // char[] prefix = prefixes[i]; // int max = prefix.length < name.length ? prefix.length : name.length; // int currLen = 0; // for (; currLen < max; currLen++) { // if(Character.toLowerCase(prefix[currLen]) != Character.toLowerCase(name[currLen])) { // if (currLen > bestLength) { // bestLength = currLen; // } // break; // } // } // if(currLen == max && currLen > bestLength) { // bestLength = max; // } // } // if(bestLength > 0) { // if(bestLength == name.length) { // withoutPrefixName = CharOperation.NO_CHAR; // } else { // withoutPrefixName = CharOperation.subarray(name, bestLength, name.length); // } // } // } return withoutPrefixName; } public static final boolean prefixEquals(char[] prefix, char[] name) { int max = prefix.length; if (name.length < max) return false; for (int i = max; --i >= 0; ) // assumes the prefix is not larger than the name if (prefix[i] != name[i]) return false; return true; } }