How do I get rid of Boolean method is always inverted warning? - kotlin

fun findError(puzzle: Array<IntArray>): Boolean {
for (z in 0..8) {
val blockNums = mutableListOf<Int>()
val xNums = mutableListOf<Int>()
val yNums = mutableListOf<Int>()
for (index in 0..8) {
xNums.add(puzzle[z][index])
yNums.add(puzzle[index][z])
blockNums.add(puzzle[blocks.xy[z + 1][index]][blocks.xy[z][index]])
if (blockNums.count() != blockNums.toSet().count() ||
yNums.count() != yNums.toSet().count() ||
xNums.count() != xNums.toSet().count()) return false
}
}
return true
}
This function works as desired but the Intellij IDE gives this warning. "Boolean method 'findError' is always inverted". I kind of understand what it means and I know I could suppress it.
I can't figure out how to rewrite the code block to satisfy the error and not change the functionality. Should I just suppress it or is there a more proper way to express this? I'm a beginner that is learning.
public final data class Blocks public constructor(blockNums: kotlin.collections.MutableList<kotlin.Int>, blockNumsFinal: kotlin.collections.MutableSet<kotlin.Int>, xy: kotlin.collections.List<kotlin.collections.List<kotlin.Int>>) {
public final val blockNums: kotlin.collections.MutableList<kotlin.Int> /* compiled code */
public final val blockNumsFinal: kotlin.collections.MutableSet<kotlin.Int> /* compiled code */
public final var xy: kotlin.collections.List<kotlin.collections.List<kotlin.Int>> /* compiled code */
public final operator fun component1(): kotlin.collections.MutableList<kotlin.Int> { /* compiled code */ }
public final operator fun component2(): kotlin.collections.MutableSet<kotlin.Int> { /* compiled code */ }
public final operator fun component3(): kotlin.collections.List<kotlin.collections.List<kotlin.Int>> { /* compiled code */ }
}
I found a way to rewrite the function not using the '!' symbol. This should satisfy the intention of the warning to use positives instead of negatives. It still gives the warning. I think Bas Leijdekkers comment about the inspection may be correct.
fun findError(puzzle: Array<IntArray>): Boolean {
val blockNums = mutableListOf<Int>()
val xNums = mutableListOf<Int>()
val yNums = mutableListOf<Int>()
var counts = 0
for (z in 0..8) {
blockNums.clear()
xNums.clear()
yNums.clear()
for (index in 0..8) {
xNums.add(puzzle[z][index])
yNums.add(puzzle[index][z])
blockNums.add(puzzle[blocks.xy[z + 1][index]][blocks.xy[z][index]])
if (blockNums.count() == blockNums.toSet().count() &&
yNums.count() == yNums.toSet().count() &&
xNums.count() == xNums.toSet().count()) {
counts++
}
}
}
return counts == 81
}

Which line is the IntelliJ warning you about, is it this statement?
if (blockNums.count() != blockNums.toSet().count() ||
yNums.count() != yNums.toSet().count() ||
xNums.count() != xNums.toSet().count()) return false
if so, it is because this is complex and likely difficult for someone other than you to understand. Here's two ideas about how you might make reduce the complexity:
(1)
if (blockNums.size != blockNums.toSet().size) return false
if (yNums.size != yNums.toSet().size) return false
if (xNums.size != xNums.toSet().size) return false
or (2)
val blocksDiffer = (blockNums.size != blockNums.toSet().size)
val yDiffer = (yNums.size != yNums.toSet().size)
val xDiffer = (xNums.size != xNums.toSet().size)
if(blocksDiffer || yDiffer || xDiffer) return false
(There is a small performance penalty with (2) since the program has to compute all 3 evaluations.
I also changed count() to size which are equivalent)

I believe this is IntelliJ trying to warn you that a boolean method result is always inverted after calling. In other words, you only ever use !findError() in your code.
This is an indication that the code could be made more readable by using positive language. JetBrain's justification for this appears to be based on Robert Martin's book Clean Code:
“Negatives are just a bit harder to understand than positives. So, when possible, conditionals should be expressed as positives.”
You can use Refactor -> Invert Boolean... to perform this automatically.

Related

Nested Loop select the minimum defined value asp.net

I have a list of states, which are defined to be ordered by min to max. the sequence is the following:
Cancelled - complete - draft - reservation - reserved - ordered - confirmed
So the cancelled is the minimum state, and confirmed is the maximum state. I may have different instances with different states, so I use a for-each loop to run through all states, and select the minimum state present in the loop.
That is: if in a list I have states [complete, reserved, draft, ordered] I need to check all the values and select complete -as it appears to be the minimum state. OR
if I have [reserved, confirmed, ordered, draft, cancelled, confirmed, confirmed] I need to select the cancelled value, as it appears to be the minimum.
I am doing the following check, but it does not seem to be working:
string globstatus = " ";
foreach (var currentstatus in list)
{
if (currentstatus == "cancelled")
{
globstatus = "cancelled";
}
else
{
if (globstatus == "cancelled")
{
return globstatus;
}
else
{
if (currentstatus == "complete")
{
globstatus = "complete";
}
else
{
if (globstatus == "complete")
{
return globstatus;
}
else
{
if (currentstatus == "draft")
{
globstatus = "draft";
}
else
{
if (globstatus == "reservation")
{
return globstatus;
}
else
{
if (currentstatus == "reserved")
{
globstatus = "reserved";
}
else
{
if (globstatus == "ordered")
{
return globstatus;
}
else
{
if (currentstatus == "confirmed")
{
globstatus = "confirmed";
}
else
{
return currentstatus;
}
}
}
}
}
}
}
}
}
}
return globstatus;
What can be the best solution to achieve the desired behavior?
I find a rule of thumb helpful that if I need more than three levels of braces, I need to rethink my code. It's hard to follow, easy to make mistakes, and a nightmare to debug. I suggest that applies here - trying to follow the flow of what all those nested if..else statements is extremely difficult.
Using Enum
My preferred solution is to achieve this using an Enum, e.g.:
var list = new List<Status>
{
Status.Complete,
Status.Draft,
Status.Draft,
Status.Confirmed
};
var minStatus = (Status)list.Select(l => (int)l).Min();
// minStatus = Status.Complete
public enum Status
{
Cancelled,
Complete,
Draft,
Reservation,
Reserved,
Ordered,
Confirmed
}
How it works: by default Enums give each value a zero-based integer, i.e. Cancelled = 0, Complete = 1 and so on. You can override this with your own values if you wish (e.g. 1/2/4/8/16 if you want to combine multiple values).
I recommend using Enum types for things like this, rather than strings. It helps avoid typos, gives someone else looking at your code a clear understanding of how your program works and its flow, and represents hierarchy in a way in which simple strings don't. (For example - does 'complete' come before or after 'draft'? Without context, I imagine most people would say after, but in this case it comes before - that is much more obvious when using an Enum.)
Parse strings to Enum
However if the statuses have to be strings, you could parse them into an enum like so:
var stringList = new List<string>
{
"complete",
"draft",
"draft",
"confirmed",
"this will be ignored"
};
var statusList = new List<int>();
foreach (var str in stringList)
{
if(Enum.TryParse(typeof(Status), str, ignoreCase: true, out object? parsed) && parsed is Status status)
{
statusList.Add((int)status);
}
}
var minStatus = (Status)statusList.Min();
// minStatus = Status.Complete
However, if it's possible to refactor your code to use the Enum in the first place, that would be a better solution, and much quicker as parsing strings has an overhead that would be good to avoid.

Null check with ?. vs ?: fails in kotlin

I have following statement in my code:
safeOrderResult.accomplished?.let{ safeAccomplished->
//Do something with safeAccomplished when accomplished <> null
Log.i(TAG,"bind: safeOrderResult.accomplishedId.let?{}")
}?:let{
//Do something when accomplished == null
Log.i(TAG,"bind: safeOrderResult.accomplishedId?:let{} *null*" )
}
Here my code does something strange:
On a Samsung TAB A (i think not significant) it works as expected.
On a Samsung S9 it calls both let sections.
Snippet from Logcat Samsung S9 (android 10)
2021-05-06 14:11:35.427 9069-9069/no.norva24.mslam I/ViewHolder: bind: safeOrderResult.accomplishedId = 408
2021-05-06 14:11:35.427 9069-9069/no.norva24.mslam I/ViewHolder: bind: safeOrderResult.accomplishedId.let?.{}
2021-05-06 14:11:35.427 9069-9069/no.norva24.mslam I/ViewHolder: bind: handleDate = null <- inside above let: ok
2021-05-06 14:11:35.427 9069-9069/no.norva24.mslam I/ViewHolder: bind: safeOrderResult.accomplishedId?:let{} *null*
2021-05-06 14:11:35.427 9069-9069/no.norva24.mslam I/ViewHolder: bind: flagged = false or null
TabA: android 10
2021-05-06 14:21:16.676 2468-2468/no.norva24.mslam I/ViewHolder: bind: safeOrderResult.accomplishedId = 427
2021-05-06 14:21:16.676 2468-2468/no.norva24.mslam I/ViewHolder: bind: safeOrderResult.accomplishedId.let?.{}
2021-05-06 14:21:16.678 2468-2468/no.norva24.mslam I/ViewHolder: bind: handleDate = null <-- inside above let
2021-05-06 14:21:16.685 2468-2468/no.norva24.mslam I/ViewHolder: bind: flagged = false or null
The key point is, how can a value both be null and contain a value?, or can kotlin "change" to null and kick in in the second "null" let, if value has changed in the first first let (which I didn't do)
I am Using kotlin 1.5.0
EDIT 2021.05.06 18:55 GMT+2
I am not sure, but I might have learned something here today: ;)
safeOrderResult.accomplished?.let{ safeAccomplished->
//Do something with safeAccomplished when accomplished <> null
/*Here I have preserved my value in safeAccomplished
And actually returning a value below (a Unit()) from Log.i ?*/
Log.i(TAG,"bind: safeOrderResult.accomplishedId.let?{}")
}?:let{
//Do something when accomplished == null
/* But why did the code kick in here ?
After it was inside the let above ? I thought the '?:let' was
continuing if the '?.let' didn't kick in.
*/
Log.i(TAG,"bind: safeOrderResult.accomplishedId?:let{} *null*" )
}
/*
Below is the actual code which had the trouble (the code isn't finished therefore the "preserved" `let` values isn't used)
*/
safeOrderResult.accomplishedId?.let {
listItemOrderListLinearLayoutCompatStatus.apply {
visibility = View.VISIBLE
listItemOrderListMaterialTextViewOrderStatus.text =
context.resources.getStringArray(
R.array.basic_register_accomplish_status_names)[1]
listItemOrderListMaterialTextViewDate.text =
dateStringSplitSpace(safeOrderResult.registeredDate)
Log.i(TAG, "bind: handleDate = ${safeOrderResult.handleDate}")
listItemOrderListMaterialTextViewReason.text =
if(safeOrderResult.handleDate.isNullOrEmpty())
"Still possible to update"
else
"Assignment locked on ${dateStringSplitSpace(safeOrderResult.handleDate)}"
setBackgroundColor(
ContextCompat.getColor(
itemView.context,
if(safeOrderResult.handleDate.isNullOrEmpty())
R.color.list_item_register_field_accomplished_background
else
R.color.list_item_register_field_accomplished_locked_background
)
)
}
listItemOrderListLinearLayoutCompatStatusMore?.apply {
setBackgroundColor(
ContextCompat.getColor(
itemView.context,
if(safeOrderResult.handleDate.isNullOrEmpty())
R.color.list_item_register_field_accomplished_background
else
R.color.list_item_register_field_accomplished_locked_background
)
)
}
}?:let {
safeOrderResult.passedId?.let { safePassedId->
listItemOrderListLinearLayoutCompatStatus.apply {
visibility = View.VISIBLE
listItemOrderListMaterialTextViewOrderStatus.text =
context.resources.getStringArray(
R.array.basic_register_accomplish_status_names
)[2]
listItemOrderListMaterialTextViewDate.text =
dateStringSplitSpace(safeOrderResult.registeredDate)
listItemOrderListMaterialTextViewReason.text =
safeOrderResult.passedReason
setBackgroundColor(
ContextCompat.getColor(
itemView.context,
R.color.list_item_register_field_passed_background,
)
)
}
}?:let {
listItemOrderListLinearLayoutCompatStatus.apply {
visibility = View.GONE
}
}
}
** ADDENDUM 2020.05.06 19:30 GMT+2 **
In playground I got trouble with this:
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
class A {
fun f() {
let { println(it) }
}
}
data class DataClass(
var value1:String?=null,
var value2:String?=null
)
fun main() {
A().f()
var myData = DataClass()
myData.value1 = "1"
myData.value1?.let{ safeValue1->
println("value1 = "+safeValue1)
}?:let{
println("value1==null !!")
}
myData.value2?.let{ safeValue2->
println("value2 = "+safeValue2)
}?:let{
println("value2==null !!")
}
}
Where it kicked on the ?:let's above. This was ok in kotin v.1.5.0 at least...
ADDENDUM 2: 2020.05.06 19:40 GMT+2
So... dataClass.value?:let{ } isn't allowed ? in a 'standard' kotlin scenario to check for null existence ?, but still 'valid' in AS2020.3.1.15 w/kotlin 1.5.0 ...
ADDENDUM 3: 2020.05.06 19:55 GMT+2
When using another approach (omitting let keyword in ?:let{ I got this answer to the based on the playground code above:
Here I expected also the value2 to show up with value2==null !! but it didn`t...
Here's the playground code now:
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
class A {
fun f() {
let { println(it) }
}
}
data class DataClass(
var value1:String?=null,
var value2:String?=null
)
fun main() {
A().f()
var myData = DataClass()
myData.value1 = "1"
/*
myData.value1?.let{ safeValue1->
println("value1 = "+safeValue1)
}?:let{
println("value1==null !!")
}
myData.value2?.let{ safeValue2->
println("value2 = "+safeValue2)
}?:let{
println("value2==null !!")
}
*/
myData.value1?.let{ safeValue1->
println("value1 = "+safeValue1)
}
myData.value1?:{
println("value1==null !!")
}
myData.value2?.let{ safeValue2->
println("value2 = "+safeValue2)
}
myData.value2?:{
println("value2==null !!")
}
}
...still a little confused ...
The let function can indeed change your target to null. It changes the target to whatever it returns. A lambda implicitly returns the result of its last expression. Your code above has a Log.i() call as its last expression, so it returns Unit, so the second let function should never run if the first one does. Is it possible you've snipped off some code at the end of your first let lambda that could possibly return a null value?
A quick fix for the above problem would be to swap let for also, because also always returns its receiver.
I think most experienced Kotlin users will advise you not to chain scope function calls like this because it makes the code hard to follow and it is easy to introduce subtle bugs. You can write a more robust version like this:
val accomplished = safeOrderResult.accomplished
if (accomplished != null) {
//Do something with smart-cast non-nullable accomplished
} else {
//Do something when accomplished == null
}
At a guess, the first one is returning null at the end, which means the value produced by that whole expression is null, so the stuff after the ?: is triggered (since that's an "if the left side evaluates to null" condition).
Why that would only happen on some Samsung models - who knows, they have a history of messing with things in the Android library! I'd check exactly what's going on in the block and what it might evaluate to. You might need to return Unit at the end, or use a function like apply that returns the receiver instead of the result of the lambda.
This is why the if/else is a better fit - you have a condition at the start, and you decide whether to do one thing or another, exclusively. let produces a value, and it's often used to propagate a value down a chain, and return a result. ?: is a final default value, for if that result turns out to be null.
It's absolutely possible to run the let block and the code after the ?:, and sometimes that a thing you want to do. As a construction it's often used for returning a default value. So if/else is a little more explicit about what you're doing and how it's meant to work, and it helps avoid surprise bugs like this one!
If you don't want to bind accomplished to a variable as in #Tenfour04's answer, I'd write it as
safeOrderResult.accomplished.let {
if (it != null) {
// safeOrderResult.accomplished was not null, use it
} else {
// safeOrderResult.accomplished was null
}
}
or
safeOrderResult.accomplished.let { accomplished ->
if (accomplished != null) {
// safeOrderResult.accomplished was not null, use accomplished
} else {
// safeOrderResult.accomplished was null
}
}
Note .let and not ?.let. But pick on readability/convenience. I definitely wouldn't use
value?.let{ safeValue-> /*dowork*/}; value?:let{/*do null work*/}
as you suggest in another comment.
You can do an if-null-else with ?.let but it's not very readable in my opinion
var s: String? = "Str"
s?.let { println("A ok") } ?: run { println("A null") }
s = null
s?.let { println("B ok") } ?: run { println("B null") }
A ok
B null
It is also possible to introduce subtle bugs like this:
var s: String? = "Str"
s?.let { println("A ok"); null } ?: run { println("A null") }
A ok
A null
This is why you should use an if-else if you both need the non-null and null case. (?. is intended for the case where only the non-null case makes sense):
if (s == null) println("A null") else println("A ok")
if (s == null) {
println("A null")
} else {
println("A ok")
}
Thanx for many good answers above, and you all are right...
I landed on following solution for my problem, but still not quite happy though:
I use .apply to remove some value. overhead,
safeOrderResult.apply{
if(accomplished!=null){
//Do something with accomplished since accomplished <> null
Log.i(TAG,"bind: accomplished != null")
}else{
//Do something when accomplished == null
Log.i(TAG,"bind: accomplished == null" )
}
}
I mark accepted for #Alexey Romanov suggestion which is quite reasonable.

Is there a way to merge filter and map into single operation in Kotlin?

The below code will look for "=" and then split them. If there's no "=", filter them away first
myPairStr.asSequence()
.filter { it.contains("=") }
.map { it.split("=") }
However seeing that we have both
.filter { it.contains("=") }
.map { it.split("=") }
Wonder if there's a single operation that could combine the operation instead of doing it separately?
You can use mapNotNull instead of map.
myPairStr.asSequence().mapNotNull { it.split("=").takeIf { it.size >= 2 } }
The takeIf function will return null if the size of the list returned by split method is 1 i.e. if = is not present in the string. And mapNotNull will take only non null values and put them in the list(which is finally returned).
In your case, this solution will work. In other scenarios, the implementation(to merge filter & map) may be different.
I see your point and under the hood split is also doing an indexOf-check to get the appropriate parts.
I do not know of any such function supporting both operations in a single one, even though such a function would basically just be similar to what we have already for the private fun split-implementation.
So if you really want both in one step (and require that functionality more often), you may want to implement your own splitOrNull-function, basically copying the current (private) split-implementation and adapting mainly 3 parts of it (the return type List<String>?, a condition if indexOf delivers a -1, we just return null; and some default values to make it easily usable (ignoreCase=false, limit=0); marked the changes with // added or // changed):
fun CharSequence.splitOrNull(delimiter: String, ignoreCase: Boolean = false, limit: Int = 0): List<String>? { // changed
require(limit >= 0, { "Limit must be non-negative, but was $limit." })
var currentOffset = 0
var nextIndex = indexOf(delimiter, currentOffset, ignoreCase)
if (nextIndex == -1 || limit == 1) {
if (currentOffset == 0 && nextIndex == -1) // added
return null // added
return listOf(this.toString())
}
val isLimited = limit > 0
val result = ArrayList<String>(if (isLimited) limit.coerceAtMost(10) else 10)
do {
result.add(substring(currentOffset, nextIndex))
currentOffset = nextIndex + delimiter.length
// Do not search for next occurrence if we're reaching limit
if (isLimited && result.size == limit - 1) break
nextIndex = indexOf(delimiter, currentOffset, ignoreCase)
} while (nextIndex != -1)
result.add(substring(currentOffset, length))
return result
}
Having such a function in place you can then summarize both, the contains/indexOf and the split, into one call:
myPairStr.asSequence()
.mapNotNull {
it.splitOrNull("=") // or: it.splitOrNull("=", limit = 2)
}
Otherwise your current approach is already good enough. A variation of it would just be to check the size of the split after splitting it (basically removing the need to write contains('=') and just checking the expected size, e.g.:
myPairStr.asSequence()
.map { it.split('=') }
.filter { it.size > 1 }
If you want to split a $key=$value-formats, where value actually could contain additional =, you may want to use the following instead:
myPairStr.asSequence()
.map { it.split('=', limit = 2) }
.filter { it.size > 1 }
// .associate { (key, value) -> key to value }

Include both assignment and test on assigned value in while loop for Kotlin

I'm looking to find the last line of a text file using a rather standard while-loop idiom I find often used in Java.
I have a less compact version working. But the one I would like to use does not appear to be valid syntax in Kotlin. My preferred method includes an assignment and a Boolean test on that assignment in the same line.
Admittedly this is a small matter, but I'm looking to better implement my Kotlin code.
fun readLastLine(file:File):String {
val bufferedReader = file.bufferedReader()
var lastLine=""
//valid
var current = bufferedReader.readLine()
while(current != null) {
lastLine=current
current = bufferedReader.readLine()
}
//return lastLine
//not valid...
//while((current=bufferedReader.readLine())!=null){
// lastLine=current
//}
//responding to comment below,
//preferred/terse answer using file.readLines
//this reads all the lines into a list, then returns the last
return file.readLines().last()
}
In Kotlin, an assignment is not an expression whose value is equal to the assigned value.
You can combine two statements using run function in Kotlin. This function returns the value of the the last expression.
var current = ""
while (run {
current = bufferedReader.readLine()
current != null
}) { // or while (run { current = bufferedReader.readLine(); current != null }) {
lastLine = current
}
However, you can further reduce the code using File.forEachLine() in Kotlin.
fun readLastLine(file: File): String {
var lastLine = ""
file.forEachLine { line ->
lastLine = line
}
return lastLine
}
Or shorter,
fun readLastLine(file: File): String {
var lastLine = ""
file.forEachLine { lastLine = it }
return lastLine
}
This uses BufferedReader and closes automatically internally: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/for-each-line.html

Cross referencing in Xtext is very slow. How do i improve it?

This is in continuation with the issue mentioned in the forum:
xtext-Couldn't-resolve-reference-to.
The sample model i am using is as below
grammar org.xtext.example.testdsl.TestDsl with org.eclipse.xtext.common.Terminals
generate testDsl "http://www.test.com/test/example/TestDsl"
Model:
prog+=Program*;
Program: g=Greeting de+=DataEntry* s+=Statement*;
Greeting: 'Hello' t=ProgPara '!';
ProgPara: 'PROGRAM' pname=Progname ';';
Progname : name=ID;
DataEntry: a=INT (v=Varname| in=Indexname) ';';
Varname : name = ID;
Statement: c=CopyStmt ';';
CopyStmt: 'COPY' 'TO' qname=[IndexVarname|ID] ;
IndexVarname : (Indexname|Varname);
Indexname : '(' name = ID ')';
Named:Progname|Indexname|Varname;
I have a file which uses similar grammar and this file is pretty big with about 12000 lines of code and 2000 odd Progname or Varname and at each instance it is trying to resolve the type in the scope provider. The grammar has about 326 elements in it.
val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, Indexname);
val candidates2 = EcoreUtil2.getAllContentsOfType(rootElement, Varname);
val candidates = candidates1 + candidates2;
return Scopes.scopeFor(candidates);
Because of repeated calls to getScope(), the file is taking for ever to open in Editor. Even if it opens any small edit is way too slow. Please suggest how i could resolve this issue.
I tried adding caching support for the above code as below:
class TestDslScopeProvider extends AbstractTestDslScopeProvider {
#Inject
IResourceScopeCache cache;
override getScope(EObject context, EReference reference) {
if (context instanceof CopyStmt) {
if (reference.featureID == TestDslPackage.COPY_STMT__QNAME) {
val candidates = cache.get(
context,
reference.eResource,
[|findQNameCandidates(context, reference)]
);
return Scopes.scopeFor(candidates);
}
}
return super.getScope(context, reference);
}
def findQNameCandidates(EObject context, EReference reference) {
val rootElement = EcoreUtil2.getRootContainer(context);
val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, Indexname);
val candidates2 = EcoreUtil2.getAllContentsOfType(rootElement, Varname);
return candidates1 + candidates2;
}
}
Even now, it is still very slow. There has been no difference. If i replace the context with reference object as key for the cache, then the speed is fast but then all cross referenced links are lost and I get errors. I am not able to point where i am not doing the right thing.
Thanks,
Anitha
the following works for me
#Inject
IResourceScopeCache cache;
override getScope(EObject context, EReference reference) {
if (context instanceof CopyStmt) {
if (reference.featureID == MyDslPackage.COPY_STMT__QNAME) {
val candidates = cache.get(
"COPY_STMT__QNAME_scope",
context.eResource,
[|findQNameCandidates(context, reference)]
);
return Scopes.scopeFor(candidates);
}
}
return super.getScope(context, reference);
}
def findQNameCandidates(EObject context, EReference reference) {
val rootElement = EcoreUtil2.getRootContainer(context);
val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, IndexVarname);
return candidates1;
}