-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Started fixing check for incomplete implementations
# Conflicts: # Shared/src/main/java/org/openzen/zencode/shared/CompileExceptionCode.java
- Loading branch information
Showing
5 changed files
with
150 additions
and
22 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
2 changes: 1 addition & 1 deletion
2
...ngEngineTester/src/main/resources/zencode_tests/interfaces/incomplete_implementation_1.zc
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
#error: 7:INCOMPLETE_IMPLEMENTATION | ||
#error: 8:INCOMPLETE_IMPLEMENTATION | ||
|
||
interface Test { | ||
print(): void; | ||
|
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
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
121 changes: 121 additions & 0 deletions
121
.../src/main/java/org/openzen/zenscript/validator/visitors/ImplementationCheckValidator.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,121 @@ | ||
package org.openzen.zenscript.validator.visitors; | ||
|
||
import org.openzen.zenscript.codemodel.compilation.CompileErrors; | ||
import org.openzen.zenscript.codemodel.definition.InterfaceDefinition; | ||
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol; | ||
import org.openzen.zenscript.codemodel.member.*; | ||
import org.openzen.zenscript.codemodel.type.TypeID; | ||
import org.openzen.zenscript.validator.Validator; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.NoSuchElementException; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
public class ImplementationCheckValidator implements MemberVisitor<Void> { | ||
|
||
private final Validator validator; | ||
private final Set<MethodSymbol> implementedMethods = new HashSet<>(); | ||
private final InterfaceDefinition interfaceDefinition; | ||
|
||
public ImplementationCheckValidator(Validator validator, ImplementationMember implementationMember) { | ||
this.validator = validator; | ||
|
||
this.interfaceDefinition = implementationMember.asImplementation() | ||
.flatMap(TypeID::asDefinition) | ||
.map(d -> d.definition) | ||
.filter(InterfaceDefinition.class::isInstance) | ||
.map(InterfaceDefinition.class::cast) | ||
.orElseThrow(() -> new NoSuchElementException("Must be an implementation!")); | ||
} | ||
|
||
@Override | ||
public Void visitField(FieldMember member) { | ||
validator.logError(member.position, CompileErrors.definitionNotAllowedHere("Field members not allowed inside an interface implementation")); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitConstructor(ConstructorMember member) { | ||
validator.logError(member.position, CompileErrors.definitionNotAllowedHere("Constructor members not allowed inside an interface implementation")); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitMethod(MethodMember member) { | ||
visitFunctional(member); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitGetter(GetterMember member) { | ||
visitFunctional(member); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitSetter(SetterMember member) { | ||
visitFunctional(member); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitOperator(OperatorMember member) { | ||
visitFunctional(member); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitCaster(CasterMember member) { | ||
visitFunctional(member); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitCustomIterator(IteratorMember member) { | ||
visitFunctional(member); | ||
return null; | ||
} | ||
|
||
private void visitFunctional(FunctionalMember member) { | ||
member.getOverrides().ifPresent(e -> { | ||
if (interfaceDefinition.equals(e.method.getDefiningType())) { | ||
if (implementedMethods.contains(e.method)) { | ||
validator.logError(member.position, CompileErrors.duplicateMember(member.toString())); | ||
return; | ||
} | ||
|
||
implementedMethods.add(e.method); | ||
} else { | ||
validator.logError(member.position, CompileErrors.invalidOverride("override not part of interface")); | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public Void visitImplementation(ImplementationMember member) { | ||
validator.logError(member.position, CompileErrors.cannotNestImplementations()); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitInnerDefinition(InnerDefinitionMember member) { | ||
validator.logError(member.position, CompileErrors.definitionNotAllowedHere("Inner definitions are not allowed inside an interface implementation")); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visitStaticInitializer(StaticInitializerMember member) { | ||
validator.logError(member.position, CompileErrors.definitionNotAllowedHere("Static initializer members not allowed inside an interface implementation")); | ||
return null; | ||
} | ||
|
||
public List<IDefinitionMember> getUnimplementedMembers() { | ||
return interfaceDefinition.members.stream() | ||
.filter(IDefinitionMember::isAbstract) | ||
.filter(o -> !implementedMethods.contains(o)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
} |