Skip to content

Commit 8b8c920

Browse files
author
Oleksandr Dzhychko
committed
fix(mps-model-adapters): return null when resolving project module in an unresolvable project
Previously, the method failed while trying to cast null to a non-null type.
1 parent d869a70 commit 8b8c920

File tree

2 files changed

+50
-1
lines changed
  • mps-model-adapters-plugin/src/test/kotlin/org/modelix/model/mpsadapters
  • mps-model-adapters/src/main/kotlin/org/modelix/model/mpsadapters

2 files changed

+50
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.modelix.model.mpsadapters
2+
3+
import org.modelix.model.api.BuiltinLanguages
4+
import org.modelix.model.api.INode
5+
6+
/*
7+
* Copyright (c) 2023.
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
*/
21+
22+
class MPSAreaTest : MpsAdaptersTestBase("SimpleProject") {
23+
24+
fun testResolveModuleInNonExistingProject() {
25+
val repositoryNode: INode = MPSRepositoryAsNode(mpsProject.repository)
26+
val area = repositoryNode.getArea()
27+
readAction {
28+
val nonExistingProject = MPSProjectReference("nonExistingProject")
29+
val module = repositoryNode.getChildren(BuiltinLanguages.MPSRepositoryConcepts.Repository.modules)
30+
.single { it.getPropertyValue(BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name) == "Solution1" }
31+
val projectModuleReference = MPSProjectModuleReference((module.reference as MPSModuleReference).moduleReference, nonExistingProject)
32+
33+
val resolutionResult = area.resolveNode(projectModuleReference)
34+
35+
assertNull(resolutionResult)
36+
}
37+
}
38+
}

mps-model-adapters/src/main/kotlin/org/modelix/model/mpsadapters/MPSArea.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,13 +306,24 @@ data class MPSArea(val repository: SRepository) : IArea, IAreaReference {
306306
val projectRef = if (ref is MPSProjectModuleReference) {
307307
ref.projectRef
308308
} else {
309+
// XXX Prefix of `projectRef` is not checked.
310+
// `projectRef` might actually be a ref to anything.
311+
// This might trigger unexpected resolution results and undefined behavior.
312+
// Similar missing checks exist for other references in `MPSArea`.
313+
// See https://issues.modelix.org/issue/MODELIX-923
309314
val projectRef = serialized.substringAfter(MPSProjectModuleReference.SEPARATOR)
310315
NodeReference(projectRef)
311316
}
312317

318+
val resolvedNodeForProject = resolveNode(projectRef) ?: return null
319+
check(resolvedNodeForProject is MPSProjectAsNode) {
320+
"Resolved node `$resolvedNodeForProject` does not represent a project."
321+
}
322+
val resolvedProject = resolvedNodeForProject.project
323+
313324
return moduleRef.resolve(repository)?.let {
314325
MPSProjectModuleAsNode(
315-
project = (resolveNode(projectRef) as MPSProjectAsNode).project,
326+
project = resolvedProject,
316327
module = it,
317328
)
318329
}

0 commit comments

Comments
 (0)