/* * Copyright (c) 2005, 2009 Sven Efftinge 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: * Sven Efftinge - Initial API and implementation * Artem Tikhomirov (Borland) - Migration to OCL expressions */ package org.eclipse.gmf.internal.xpand.ast; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EPackage.Registry; import org.eclipse.gmf.internal.xpand.ast.analyze.UnusedMetamodelsCollector; import org.eclipse.gmf.internal.xpand.ast.analyze.UnusedModulesCollector; import org.eclipse.gmf.internal.xpand.expression.ast.SyntaxElement; import org.eclipse.gmf.internal.xpand.model.AnalysationIssue; import org.eclipse.gmf.internal.xpand.model.ExecutionContext; import org.eclipse.gmf.internal.xpand.model.XpandAdvice; import org.eclipse.gmf.internal.xpand.model.XpandDefinition; import org.eclipse.gmf.internal.xpand.model.XpandResource; import org.eclipse.gmf.internal.xpand.xtend.ast.QvtResource; import org.eclipse.m2m.internal.qvt.oml.expressions.Module; /** * XXX why it's SyntaxElement? What does 'getLine()' means? * * @author Sven Efftinge */ public class Template extends SyntaxElement implements XpandResource { private final NamespaceImport[] imports; private final Definition[] definitions; private final ImportDeclaration[] extensions; private final Advice[] advices; private String qualifiedName; private String[] importStrings = null; private String[] importedExtensions = null; public Template(final int start, final int end, final int line, final NamespaceImport[] imports, final ImportDeclaration[] extensions, final Definition[] definitions, final Advice[] advices) { super(start, end, line); this.imports = imports; this.extensions = extensions; for (Definition element : definitions) { element.setOwner(this); } this.definitions = definitions; for (Advice element : advices) { element.setOwner(this); } this.advices = advices; } public String getFullyQualifiedName() { // XXX what's the reason to have both file name and qualified name? return qualifiedName == null ? getFileName() : qualifiedName; } public void setFullyQualifiedName(String name) { qualifiedName = name; } public XpandDefinition[] getDefinitions() { return definitions; } public void analyze(ExecutionContext ctx, final Set<AnalysationIssue> issues) { ctx = ctx.cloneWithResource(this); // for (ImportDeclaration importDeclaration : extensions) { // QvtResource extension = // ctx.getScope().findExtension(importDeclaration.getImportString()); // if (extension == null) { // issues.add(new // AnalysationIssue(AnalysationIssue.Type.EXTENSION_NOT_FOUND, // "Couldn't find " + importDeclaration.getImportString(), // importDeclaration)); // } else { // for (Module module : extension.getModules()) { // } // } // } // for (Definition element : definitions) { element.analyze(ctx, issues); } for (Advice element : advices) { element.analyze(ctx, issues); } Map<Module, ImportDeclaration> module2ImportDeclarationMap = new LinkedHashMap<Module, ImportDeclaration>(); for (ImportDeclaration importDeclaration : extensions) { QvtResource extension = ctx.getScope().findExtension(importDeclaration.getImportString()); if (extension == null) { issues.add(new AnalysationIssue(AnalysationIssue.Type.EXTENSION_NOT_FOUND, "Couldn't find " + importDeclaration.getImportString(), importDeclaration)); } else { for (Module module : extension.getModules()) { module2ImportDeclarationMap.put(module, importDeclaration); } } } Map<EPackage, NamespaceImport> ePackage2NapespaceImportMap = new LinkedHashMap<EPackage, NamespaceImport>(); Registry packageRegistry = ctx.getScope().createPackageRegistry(getImportedNamespaces()); for (NamespaceImport namespaceImport : imports) { if (!packageRegistry.containsKey(namespaceImport.getImportString())) { issues.add(new AnalysationIssue(AnalysationIssue.Type.NAMESPACE_NOT_FOUND, "Couldn't find " + namespaceImport.getImportString(), namespaceImport)); } else { ePackage2NapespaceImportMap.put(packageRegistry.getEPackage(namespaceImport.getImportString()), namespaceImport); } } addWarnings(module2ImportDeclarationMap, ePackage2NapespaceImportMap, ctx, issues); } private void addWarnings(Map<Module, ImportDeclaration> module2ImportDeclarationMap, Map<EPackage, NamespaceImport> ePackage2NapespaceImportMap, ExecutionContext ctx, Set<AnalysationIssue> issues) { UnusedModulesCollector unusedModulesCollector = new UnusedModulesCollector(module2ImportDeclarationMap.keySet()); UnusedMetamodelsCollector unusedMetamodelsCollector = new UnusedMetamodelsCollector(ePackage2NapespaceImportMap.keySet(), ctx); new AstIterator(new CompositeAstVisitor(unusedModulesCollector, unusedMetamodelsCollector)).iterate(this); for (Module unusedModule : unusedModulesCollector.getUnusedModules()) { ImportDeclaration importDeclaration = module2ImportDeclarationMap.get(unusedModule); issues.add(new AnalysationIssue(AnalysationIssue.Type.UNUSED_IMPORT, "Extension " + importDeclaration.getImportString() + " is never used", importDeclaration, true)); } for (EPackage unusedEPackage : unusedMetamodelsCollector.getUnusedEPackages()) { NamespaceImport namespaceImport = ePackage2NapespaceImportMap.get(unusedEPackage); issues.add(new AnalysationIssue(AnalysationIssue.Type.UNUSED_IMPORT, "Import " + namespaceImport.getImportString() + " is never used", namespaceImport, true)); } } // XXX is it really worth it to kepp imports as ast nodes? // Is it performance gain to duplicate them here with string[]? public String[] getImportedNamespaces() { if (importStrings == null) { importStrings = new String[imports.length]; for (int i = 0; i < importStrings.length; i++) { importStrings[i] = imports[i].getImportString(); } } return importStrings; } public String[] getImportedExtensions() { if (importedExtensions == null) { importedExtensions = new String[extensions.length]; for (int i = 0; i < extensions.length; i++) { importedExtensions[i] = extensions[i].getImportString(); } } return importedExtensions; } public XpandAdvice[] getAdvices() { return advices; } }