Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Pieter Koopman
Personal Prof public repository
Commits
4547a04a
Commit
4547a04a
authored
Feb 14, 2020
by
Markus Klinik
Browse files
move ImplementsAbstractMethod to ClassHierarchy
parent
023a37d4
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/ClassHierarchy.rsc
View file @
4547a04a
...
...
@@ -3,6 +3,7 @@ module ClassHierarchy
import lang::java::m3::Core;
import Message;
import Set;
import Relation;
import Util;
...
...
@@ -209,3 +210,25 @@ set[Message] methodDependsOn(M3 model, str dependerClassName, str dependerMethod
}
return {};
}
// Given an M3 model, a class and an abstract function, determine whether the
// class implements the function.
bool implementsAbstractMethod(M3 model, loc class, loc function)
{
// transitive closure of extends and implements
// TODO: should this be (model.extends*) + (model.implements*) ?
// see https://stackoverflow.com/questions/57525714/m3-java-how-to-check-that-a-class-implements-a-function-from-an-interface
rel[loc,loc] super = (model.extends + model.implements)*;
// All methods that the class overrides
// TODO: this can be achieved easier using domainR
rel[loc,loc] allOverrides = ident(union({methods(model,s) | s <- super[class]})) o model.methodOverrides;
// All methods that override the function
functionOverrides = invert(allOverrides)[function];
return size(functionOverrides) > 0;
}
src/ImplementsAbstractMethod.rsc
deleted
100644 → 0
View file @
023a37d4
module ImplementsAbstractMethod
import Relation;
import Set;
import lang::java::m3::Core;
// Given an M3 model, a class and an abstract function, determine whether the
// class implements the function.
bool implementsAbstractMethod(M3 model, loc class, loc function)
{
// transitive closure of extends and implements
// TODO: should this be (model.extends*) + (model.implements*) ?
// see https://stackoverflow.com/questions/57525714/m3-java-how-to-check-that-a-class-implements-a-function-from-an-interface
rel[loc,loc] super = (model.extends + model.implements)*;
// All methods that the class overrides
// TODO: this can be achieved easier using domainR
rel[loc,loc] allOverrides = ident(union({methods(model,s) | s <- super[class]})) o model.methodOverrides;
// All methods that override the function
functionOverrides = invert(allOverrides)[function];
return size(functionOverrides) > 0;
}
\ No newline at end of file
src/test/ClassHierarchySpec.rsc
View file @
4547a04a
...
...
@@ -114,3 +114,52 @@ test bool classDoesntImplementInterface()
{ "|java+class:///A| should implement |java+interface:///MyInterface|" }
<= messages(errors);
}
test bool implementsInterfaceDirectly()
{
M3 model = loadTestProject("ImplementsInterface-test-data/directly-implements-interface");
return implementsAbstractMethod(model, |java+class:///A|, |java+method:///MyInterface/myAbstractFunction()|);
}
test bool implementsInterfaceIndirectly()
{
M3 model = loadTestProject("ImplementsInterface-test-data/indirectly-implements-interface");
return implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
}
test bool doesntImplementInterface()
{
M3 model = loadTestProject("ImplementsInterface-test-data/doesnt-implement-interface");
return !implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
}
// How to detect that the interface itself has an implementation?
// This is currently a false positive.
test bool defaultImplementationInInterface()
{
return true;
/*
M3 model = loadTestProject("ImplementsInterface-test-data/default-implementation-in-interface");
return implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
*/
}
// The problem here is that methodOverrides states that IntermediateInterface overrides
// MyInterface/myAbstractFunction, even though it just declares it. In my opinion this
// is a bug. But: because this produces a compile error, I would argue that we don't need
// to generate an error message here.
test bool intermediateInterfaceDeclaresFunction()
{
return true;
/*
M3 model = loadTestProject("ImplementsInterface-test-data/intermediate-interface-declares-function");
return !implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
*/
}
test bool intermediateInterfaceDefaultImplementsFunction()
{
M3 model = loadTestProject("ImplementsInterface-test-data/intermediate-interface-default-implements-function");
return implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
}
\ No newline at end of file
src/test/ImplementsAbstractMethodSpec.rsc
deleted
100644 → 0
View file @
023a37d4
module \test::ImplementsAbstractMethodSpec
import lang::java::m3::Core;
import ImplementsAbstractMethod;
import \test::SpecUtil;
test bool implementsInterfaceDirectly()
{
M3 model = loadTestProject("ImplementsInterface-test-data/directly-implements-interface");
return implementsAbstractMethod(model, |java+class:///A|, |java+method:///MyInterface/myAbstractFunction()|);
}
test bool implementsInterfaceIndirectly()
{
M3 model = loadTestProject("ImplementsInterface-test-data/indirectly-implements-interface");
return implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
}
test bool doesntImplementInterface()
{
M3 model = loadTestProject("ImplementsInterface-test-data/doesnt-implement-interface");
return !implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
}
// How to detect that the interface itself has an implementation?
// This is currently a false positive.
test bool defaultImplementationInInterface()
{
return true;
/*
M3 model = loadTestProject("ImplementsInterface-test-data/default-implementation-in-interface");
return implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
*/
}
// The problem here is that methodOverrides states that IntermediateInterface overrides
// MyInterface/myAbstractFunction, even though it just declares it. In my opinion this
// is a bug. But: because this produces a compile error, I would argue that we don't need
// to generate an error message here.
test bool intermediateInterfaceDeclaresFunction()
{
return true;
/*
M3 model = loadTestProject("ImplementsInterface-test-data/intermediate-interface-declares-function");
return !implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
*/
}
test bool intermediateInterfaceDefaultImplementsFunction()
{
M3 model = loadTestProject("ImplementsInterface-test-data/intermediate-interface-default-implements-function");
return implementsAbstractMethod(model, |java+class:///B|, |java+method:///MyInterface/myAbstractFunction()|);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment