/* * Copyright (c) 2006, 2007 Borland Software Corporation * * 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: * Anna Karjakina (Borland) - initial API and implementation */ package org.eclipse.gmf.internal.common.codegen; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.PackageDeclaration; import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; class PackageReferencesCollector extends ASTVisitor { public static void collect(ASTNode node, Collection<Name> resultingQualifiedTypeReferences, Collection<SimpleName> resultingSimpleTypeReferences, Collection<String> resultingImportDeclarations) { node.accept(new PackageReferencesCollector(resultingQualifiedTypeReferences, resultingSimpleTypeReferences, resultingImportDeclarations)); } public static void collect(ASTNode node, Collection<Name> resultingQualifiedTypeReferences, Collection<SimpleName> resultingSimpleTypeReferences, Collection<String> resultingImportDeclarations, Collection<String> hardcodedTypeNames) { node.accept(new PackageReferencesCollector(resultingQualifiedTypeReferences, resultingSimpleTypeReferences, resultingImportDeclarations, hardcodedTypeNames)); } private Collection<SimpleName> mySimpleTypeReferences; private Collection<Name> myQualifiedTypeReferences; private Collection<String> myImportDeclarations; private Collection<String> myKnownPackages = new HashSet<String>(); private Collection<String> myHardcodedTypes; private PackageReferencesCollector(Collection<Name> resultingTypeReferences, Collection<SimpleName> resultingSimpleTypeReferences, Collection<String> resultingImportDeclarations) { this(resultingTypeReferences, resultingSimpleTypeReferences, resultingImportDeclarations, null); } private PackageReferencesCollector(Collection<Name> resultingTypeReferences, Collection<SimpleName> resultingSimpleTypeReferences, Collection<String> resultingImportDeclarations, Collection<String> hardcodedTypes) { super(true); myQualifiedTypeReferences = resultingTypeReferences; mySimpleTypeReferences = resultingSimpleTypeReferences; myImportDeclarations = resultingImportDeclarations; myHardcodedTypes = hardcodedTypes; } private void addQualifiedReference(QualifiedName node) { myKnownPackages.add(node.getQualifier().getFullyQualifiedName()); myQualifiedTypeReferences.add(node); } private void addSimpleReference(SimpleName name) { mySimpleTypeReferences.add(name); } private void addImport(Name name) { if (name.isQualifiedName()) { QualifiedName qName = (QualifiedName) name; myImportDeclarations.add(qName.getName().getFullyQualifiedName()); myKnownPackages.add(qName.getQualifier().getFullyQualifiedName()); } else { addSimpleReference((SimpleName) name); } } protected void typeRefFound(Name node) { Name name = node; if (node.isQualifiedName()) { name = hackRecognizeTypesAndPackagesForTheirLettersCase((QualifiedName) node); if (name == null) { return; } } if (name.isQualifiedName()) { addQualifiedReference((QualifiedName) name); } else { addSimpleReference((SimpleName) name); } } protected Name hackRecognizeTypesAndPackagesForTheirLettersCase(QualifiedName node) { Name name = node; List<Name> qualifiers = new ArrayList<Name>(); while (name.isQualifiedName()) { qualifiers.add(name); name = ((QualifiedName) name).getQualifier(); } qualifiers.add(name); for (ListIterator<Name> it=qualifiers.listIterator(qualifiers.size()); it.hasPrevious();) { Name packagePart = it.previous(); if (getHardcodedTypes().contains(packagePart.getFullyQualifiedName())) { return packagePart; } SimpleName lastPart = packagePart.isSimpleName() ? (SimpleName)packagePart : ((QualifiedName)packagePart).getName(); char[] letters = lastPart.getFullyQualifiedName().toCharArray(); if (letters.length > 0) { if (Character.isUpperCase(letters[0])) { //XXX: Type reference is recognized for its first Upper letter and at least one Lower for (int i=0; i<letters.length; i++) { if (Character.isLowerCase(letters[i])) { return packagePart; } } } else { //XXX: Package reference is recognized for all its chars are Lower case or digits for (int i=0; i<letters.length; i++) { if (!(Character.isLowerCase(letters[i]) || Character.isDigit(letters[i]))) { return null; } } } } } return null; } public Collection<String> getHardcodedTypes() { if (myHardcodedTypes == null) { myHardcodedTypes = new HashSet<String>(); initializeDefaultHardcodedTypes(myHardcodedTypes); } return myHardcodedTypes; } protected void initializeDefaultHardcodedTypes(Collection<String> container) { container.add(SWT.class.getCanonicalName()); container.add(NLS.class.getCanonicalName()); container.add(URI.class.getCanonicalName()); } public boolean visit(ImportDeclaration node) { if (node.isOnDemand()) { myKnownPackages.add(node.getName().getFullyQualifiedName()); } else { addImport(node.getName()); } // not to visit the qualified name in imports return false; } public boolean visit(PackageDeclaration node) { // not to visit the qualified name in imports return false; } public boolean visit(SimpleType node) { typeRefFound(node.getName()); return false; } public boolean visit(TypeDeclaration node) { addSimpleReference(node.getName()); return true; } public boolean visit(QualifiedName node) { typeRefFound(node); return false; } }