-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for @this annotation in the JsInterop-generator and clean…
… up elemental2 diff that were removing @this annotation. We differentiate two cases: - @this {THIS} @template THIS: this is used in closure type system to reflect the class used when a method is called. This pattern is used for allowing subclasses methods chaining. When this pattern is used, we will just use the enclosing type of the method as return type. This is the current behavior we have with the diff solution. A better solution would be to override the method by specializing the return type on each known subclasses. - Generic methods: Generic methods use @this for redefining the minimum contract that has to be satisfied by the instance the method is called on. For that purpose, they also redefine the template types at method level. For the java conversion purpose, we ignore the @this annotation and we don't redefine the template type (used in @this annotation) at the method level. I've also created google/elemental2#107 that propose a possible improvement for generic methods PiperOrigin-RevId: 245975596
- Loading branch information
1 parent
0b9ff4d
commit fadccf4
Showing
10 changed files
with
403 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
java/jsinterop/generator/closure/helper/AbstractNoOpVisitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
* Copyright 2019 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 | ||
* | ||
* https://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 jsinterop.generator.closure.helper; | ||
|
||
import com.google.javascript.rhino.jstype.EnumElementType; | ||
import com.google.javascript.rhino.jstype.FunctionType; | ||
import com.google.javascript.rhino.jstype.NamedType; | ||
import com.google.javascript.rhino.jstype.NoType; | ||
import com.google.javascript.rhino.jstype.ObjectType; | ||
import com.google.javascript.rhino.jstype.ProxyObjectType; | ||
import com.google.javascript.rhino.jstype.TemplateType; | ||
import com.google.javascript.rhino.jstype.TemplatizedType; | ||
import com.google.javascript.rhino.jstype.UnionType; | ||
import com.google.javascript.rhino.jstype.Visitor; | ||
|
||
/** | ||
* Nominal implementation of Visitor<T> returning null for every methods. The purpose of this class | ||
* is to reduce boiler plate code when we are interested to visit small number of kind of types. | ||
*/ | ||
public abstract class AbstractNoOpVisitor<T> implements Visitor<T> { | ||
@Override | ||
public T caseNoType(NoType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseEnumElementType(EnumElementType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseAllType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseBooleanType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseNoObjectType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseFunctionType(FunctionType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseObjectType(ObjectType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseUnknownType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseNullType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseNamedType(NamedType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseProxyObjectType(ProxyObjectType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseNumberType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseStringType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseSymbolType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseVoidType() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseUnionType(UnionType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseTemplatizedType(TemplatizedType type) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public T caseTemplateType(TemplateType templateType) { | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
java/jsinterop/generator/closure/visitor/ThisTemplateTypeVisitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright 2019 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 | ||
* | ||
* https://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 jsinterop.generator.closure.visitor; | ||
|
||
import com.google.javascript.rhino.jstype.FunctionType; | ||
import com.google.javascript.rhino.jstype.JSType; | ||
import com.google.javascript.rhino.jstype.TemplateType; | ||
import java.util.ArrayDeque; | ||
import java.util.Deque; | ||
import java.util.Optional; | ||
import jsinterop.generator.closure.helper.GenerationContext; | ||
|
||
/** | ||
* Visit methods scanning for @this annotations that declare the receiver type to be just a template | ||
* variable defined in the method. | ||
* | ||
* <p>In the Closure type system, @this annotation can be used on a method to specify (or customize) | ||
* the type of the instance the method is called on. Because the template variable can be any type, | ||
* this pattern is useful for allowing seamless fluent style method even in subclasses. | ||
* | ||
* <p>This visitor is used to record these type variables so that they can be handled in a | ||
* meaningful way by the generator. | ||
*/ | ||
public class ThisTemplateTypeVisitor extends AbstractClosureVisitor { | ||
private final Deque<JSType> currentJsTypeStack = new ArrayDeque<>(); | ||
|
||
public ThisTemplateTypeVisitor(GenerationContext context) { | ||
super(context); | ||
} | ||
|
||
@Override | ||
protected boolean visitClassOrInterface(FunctionType type) { | ||
currentJsTypeStack.push(type.getInstanceType()); | ||
return true; | ||
} | ||
|
||
@Override | ||
protected void endVisitClassOrInterface(FunctionType type) { | ||
currentJsTypeStack.pop(); | ||
} | ||
|
||
@Override | ||
protected boolean visitMethod(FunctionType method, boolean isStatic) { | ||
Optional<TemplateType> thisTemplateType = getThisTemplateType(method); | ||
thisTemplateType.ifPresent( | ||
templateType -> | ||
getJavaTypeRegistry() | ||
.registerThisTemplateType(templateType, currentJsTypeStack.peek())); | ||
return true; | ||
} | ||
|
||
private Optional<TemplateType> getThisTemplateType(FunctionType type) { | ||
return type.getTypeOfThis().isTemplateType() | ||
? Optional.of(type.getTypeOfThis().toMaybeTemplateType()) | ||
: Optional.empty(); | ||
} | ||
} |
Oops, something went wrong.