blob: 4e77ddc10a100f04e43b9a263d44005ce3226d7a [file] [log] [blame]
/*
* Copyright (c) 2011 Google Inc.
*
* 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
*/
package com.google.eclipse.protobuf.scoping;
import static org.eclipse.emf.common.util.URI.createURI;
import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
import static org.eclipse.xtext.resource.EObjectDescription.create;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.eclipse.xtext.scoping.impl.ImportUriResolver;
import org.eclipse.xtext.scoping.impl.SimpleScope;
import com.google.eclipse.protobuf.protobuf.Enum;
import com.google.eclipse.protobuf.protobuf.Import;
import com.google.eclipse.protobuf.protobuf.Literal;
import com.google.eclipse.protobuf.protobuf.LiteralRef;
import com.google.eclipse.protobuf.protobuf.Option;
import com.google.eclipse.protobuf.protobuf.Property;
import com.google.eclipse.protobuf.protobuf.Protobuf;
import com.google.eclipse.protobuf.protobuf.Type;
import com.google.eclipse.protobuf.protobuf.TypeReference;
import com.google.eclipse.protobuf.util.EObjectFinder;
import com.google.inject.Inject;
/**
* Custom scoping description.
*
* @author alruiz@google.com (Alex Ruiz)
*
* @see http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping
*/
public class ProtobufScopeProvider extends AbstractDeclarativeScopeProvider {
private static final boolean DO_NOT_IGNORE_CASE = false;
@Inject private EObjectFinder finder;
@Inject private Globals globals;
@Inject private IQualifiedNameProvider nameProvider;
@Inject private ImportUriResolver uriResolver;
@SuppressWarnings("unused")
IScope scope_TypeReference_type(TypeReference typeRef, EReference reference) {
Protobuf root = finder.rootOf(typeRef);
List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
for (Type type : getAllContentsOfType(root, Type.class)) {
descriptions.add(describeUsingQualifiedName(type));
descriptions.add(create(type.getName(), type));
}
descriptions.addAll(importedTypes(root));
return createScope(descriptions);
}
private List<IEObjectDescription> importedTypes(Protobuf root) {
ResourceSet resourceSet = root.eResource().getResourceSet();
List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
for (Import anImport : root.getImports()) {
URI importUri = createURI(uriResolver.apply(anImport));
Resource imported = resourceSet.getResource(importUri, true);
descriptions.addAll(describeTypesUsingQualifiedNames(imported));
}
return descriptions;
}
private List<IEObjectDescription> describeTypesUsingQualifiedNames(Resource resource) {
List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
TreeIterator<Object> contents = getAllContents(resource, true);
while (contents.hasNext()) {
Object next = contents.next();
if (!(next instanceof Type)) continue;
descriptions.add(describeUsingQualifiedName((Type) next));
}
return descriptions;
}
private IEObjectDescription describeUsingQualifiedName(Type type) {
return create(nameProvider.getFullyQualifiedName(type), type);
}
@SuppressWarnings("unused")
IScope scope_LiteralRef_literal(LiteralRef literalRef, EReference reference) {
EObject container = literalRef.eContainer();
if (container instanceof Property) {
Enum enumType = finder.enumTypeOf((Property) container);
if (enumType != null) return scopeForLiterals(enumType);
}
if (container instanceof Option && globals.isOptimizeForOption((Option) container)) {
Enum optimizedMode = globals.optimizedMode();
return scopeForLiterals(optimizedMode);
}
return null;
}
private static IScope scopeForLiterals(Enum enumType) {
List<IEObjectDescription> descriptions = describeLiterals(enumType);
return createScope(descriptions);
}
private static List<IEObjectDescription> describeLiterals(Enum enumType) {
List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
for (Literal literal : enumType.getLiterals())
descriptions.add(create(literal.getName(), literal));
return descriptions;
}
private static IScope createScope(List<IEObjectDescription> descriptions) {
return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
}
}