blob: 2b72edfdec60abf8ef5d3e1fc314a09477590216 [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.web.bindery.requestfactory.apt;
import com.google.gwt.dev.util.Name.BinaryName;
import com.google.web.bindery.requestfactory.shared.JsonRpcProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.ProxyForName;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.TypeMirror;
/**
* Examines the methods declared in a proxy interface. Also records the client
* to domain mapping for the proxy type.
*/
class ProxyScanner extends ScannerBase<Void> {
@Override
public Void visitExecutable(ExecutableElement x, State state) {
if (shouldIgnore(x, state)) {
return null;
}
if (isGetter(x, state)) {
TypeMirror returnType = x.getReturnType();
if (!state.isTransportableType(returnType)) {
state.poison(x, Messages.untransportableType(returnType));
}
} else if (!isSetter(x, state)) {
state.poison(x, Messages.proxyOnlyGettersSetters());
}
// Parameters checked by visitVariable
return super.visitExecutable(x, state);
}
@Override
public Void visitType(TypeElement x, State state) {
ProxyFor proxyFor = x.getAnnotation(ProxyFor.class);
ProxyForName proxyForName = x.getAnnotation(ProxyForName.class);
JsonRpcProxy jsonRpcProxy = x.getAnnotation(JsonRpcProxy.class);
if (proxyFor != null) {
poisonIfAnnotationPresent(state, x, proxyForName, jsonRpcProxy);
// See javadoc on Element.getAnnotation() for why it works this way
try {
proxyFor.value();
throw new RuntimeException("Should not reach here");
} catch (MirroredTypeException expected) {
TypeMirror type = expected.getTypeMirror();
state.addMapping(x, (TypeElement) state.types.asElement(type));
}
}
if (proxyForName != null) {
poisonIfAnnotationPresent(state, x, jsonRpcProxy);
TypeElement domain =
state.elements.getTypeElement(BinaryName.toSourceName(proxyForName.value()));
if (domain == null) {
state.warn(x, Messages.proxyMissingDomainType(proxyForName.value()));
}
state.addMapping(x, domain);
}
scanAllInheritedMethods(x, state);
state.checkExtraTypes(x);
return null;
}
@Override
public Void visitVariable(VariableElement x, State state) {
if (!state.isTransportableType(x.asType())) {
state.poison(x, Messages.untransportableType(x.asType()));
}
return super.visitVariable(x, state);
}
@Override
protected boolean shouldIgnore(ExecutableElement x, State state) {
// Ignore overrides of stableId()
if (x.getSimpleName().contentEquals("stableId") && x.getParameters().isEmpty()) {
return true;
}
return super.shouldIgnore(x, state);
}
}