[FIR, LT] Report syntax error by traversing LT after parsing
#KT-57756 Fixed
This commit is contained in:
committed by
Space Team
parent
b07e4f26ef
commit
3c66ae0f8b
+48
-21
@@ -7,14 +7,14 @@ package org.jetbrains.kotlin.fir.lightTree
|
|||||||
|
|
||||||
import com.intellij.lang.LighterASTNode
|
import com.intellij.lang.LighterASTNode
|
||||||
import com.intellij.lang.PsiBuilderFactory
|
import com.intellij.lang.PsiBuilderFactory
|
||||||
|
import com.intellij.lang.impl.PsiBuilderImpl
|
||||||
|
import com.intellij.openapi.util.Ref
|
||||||
|
import com.intellij.psi.TokenType
|
||||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||||
import org.jetbrains.kotlin.KtIoFileSourceFile
|
import org.jetbrains.kotlin.KtIoFileSourceFile
|
||||||
import org.jetbrains.kotlin.KtSourceFile
|
import org.jetbrains.kotlin.KtSourceFile
|
||||||
import org.jetbrains.kotlin.KtSourceFileLinesMapping
|
import org.jetbrains.kotlin.KtSourceFileLinesMapping
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticContext
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
@@ -30,16 +30,44 @@ import java.nio.file.Path
|
|||||||
class LightTree2Fir(
|
class LightTree2Fir(
|
||||||
val session: FirSession,
|
val session: FirSession,
|
||||||
private val scopeProvider: FirScopeProvider,
|
private val scopeProvider: FirScopeProvider,
|
||||||
private val diagnosticsReporter: DiagnosticReporter? = null
|
private val diagnosticsReporter: DiagnosticReporter? = null,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private val parserDefinition = KotlinParserDefinition()
|
private val parserDefinition = KotlinParserDefinition()
|
||||||
private fun makeLexer() = KotlinLexer()
|
private fun makeLexer() = KotlinLexer()
|
||||||
|
|
||||||
fun buildLightTree(code: CharSequence): FlyweightCapableTreeStructure<LighterASTNode> {
|
fun buildLightTree(
|
||||||
|
code: CharSequence,
|
||||||
|
errorListener: LightTreeParsingErrorListener?,
|
||||||
|
): FlyweightCapableTreeStructure<LighterASTNode> {
|
||||||
val builder = PsiBuilderFactory.getInstance().createBuilder(parserDefinition, makeLexer(), code)
|
val builder = PsiBuilderFactory.getInstance().createBuilder(parserDefinition, makeLexer(), code)
|
||||||
return KotlinLightParser.parse(builder)
|
return KotlinLightParser.parse(builder).also {
|
||||||
|
if (errorListener != null) reportErrors(it.root, it, errorListener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reportErrors(
|
||||||
|
node: LighterASTNode,
|
||||||
|
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||||
|
errorListener: LightTreeParsingErrorListener,
|
||||||
|
ref: Ref<Array<LighterASTNode?>> = Ref<Array<LighterASTNode?>>(),
|
||||||
|
) {
|
||||||
|
tree.getChildren(node, ref)
|
||||||
|
val kidsArray = ref.get() ?: return
|
||||||
|
|
||||||
|
for (kid in kidsArray) {
|
||||||
|
if (kid == null) break
|
||||||
|
val tokenType = kid.tokenType
|
||||||
|
if (tokenType == TokenType.ERROR_ELEMENT) {
|
||||||
|
val message = PsiBuilderImpl.getErrorMessage(kid)
|
||||||
|
errorListener.onError(kid.startOffset, kid.endOffset, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.set(null)
|
||||||
|
reportErrors(kid, tree, errorListener, ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildFirFile(path: Path): FirFile {
|
fun buildFirFile(path: Path): FirFile {
|
||||||
@@ -57,21 +85,20 @@ class LightTree2Fir(
|
|||||||
fun buildFirFile(
|
fun buildFirFile(
|
||||||
lightTree: FlyweightCapableTreeStructure<LighterASTNode>,
|
lightTree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||||
sourceFile: KtSourceFile,
|
sourceFile: KtSourceFile,
|
||||||
linesMapping: KtSourceFileLinesMapping
|
linesMapping: KtSourceFileLinesMapping,
|
||||||
): FirFile =
|
): FirFile {
|
||||||
DeclarationsConverter(
|
return DeclarationsConverter(session, scopeProvider, lightTree)
|
||||||
session, scopeProvider, lightTree, diagnosticsReporter = diagnosticsReporter,
|
.convertFile(lightTree.root, sourceFile, linesMapping)
|
||||||
diagnosticContext = makeDiagnosticContext(sourceFile.path)
|
}
|
||||||
).convertFile(lightTree.root, sourceFile, linesMapping)
|
|
||||||
|
|
||||||
fun buildFirFile(code: CharSequence, sourceFile: KtSourceFile, linesMapping: KtSourceFileLinesMapping): FirFile =
|
fun buildFirFile(code: CharSequence, sourceFile: KtSourceFile, linesMapping: KtSourceFileLinesMapping): FirFile {
|
||||||
buildFirFile(buildLightTree(code), sourceFile, linesMapping)
|
val errorListener = makeErrorListener(sourceFile)
|
||||||
|
val lightTree = buildLightTree(code, errorListener)
|
||||||
|
return buildFirFile(lightTree, sourceFile, linesMapping)
|
||||||
|
}
|
||||||
|
|
||||||
private fun makeDiagnosticContext(path: String?) =
|
private fun makeErrorListener(sourceFile: KtSourceFile): LightTreeParsingErrorListener? {
|
||||||
if (diagnosticsReporter == null) null else object : DiagnosticContext {
|
val diagnosticsReporter = diagnosticsReporter ?: return null
|
||||||
override val containingFilePath = path
|
return diagnosticsReporter.toKotlinParsingErrorListener(sourceFile, session.languageVersionSettings)
|
||||||
override val languageVersionSettings: LanguageVersionSettings get() = session.languageVersionSettings
|
}
|
||||||
override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.lightTree
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtOffsetsOnlySourceElement
|
||||||
|
import org.jetbrains.kotlin.KtSourceFile
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticContext
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.builder.FirSyntaxErrors
|
||||||
|
|
||||||
|
fun interface LightTreeParsingErrorListener {
|
||||||
|
fun onError(startOffset: Int, endOffset: Int, message: String?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DiagnosticReporter.toKotlinParsingErrorListener(
|
||||||
|
sourceFile: KtSourceFile,
|
||||||
|
languageVersionSettings: LanguageVersionSettings
|
||||||
|
): LightTreeParsingErrorListener {
|
||||||
|
val diagnosticContext = object : DiagnosticContext {
|
||||||
|
override val containingFilePath = sourceFile.path
|
||||||
|
override val languageVersionSettings: LanguageVersionSettings get() = languageVersionSettings
|
||||||
|
override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean = false
|
||||||
|
}
|
||||||
|
return LightTreeParsingErrorListener { startOffset, endOffset, message ->
|
||||||
|
reportOn(
|
||||||
|
KtOffsetsOnlySourceElement(startOffset, endOffset),
|
||||||
|
FirSyntaxErrors.SYNTAX,
|
||||||
|
message.orEmpty(),
|
||||||
|
diagnosticContext,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-13
@@ -29,8 +29,6 @@ abstract class BaseConverter(
|
|||||||
) : BaseFirBuilder<LighterASTNode>(baseSession, context) {
|
) : BaseFirBuilder<LighterASTNode>(baseSession, context) {
|
||||||
protected val implicitType = FirImplicitTypeRefImplWithoutSource
|
protected val implicitType = FirImplicitTypeRefImplWithoutSource
|
||||||
|
|
||||||
protected open fun reportSyntaxError(node: LighterASTNode) {}
|
|
||||||
|
|
||||||
override fun LighterASTNode.toFirSourceElement(kind: KtFakeSourceElementKind?): KtLightSourceElement {
|
override fun LighterASTNode.toFirSourceElement(kind: KtFakeSourceElementKind?): KtLightSourceElement {
|
||||||
val startOffset = tree.getStartOffset(this)
|
val startOffset = tree.getStartOffset(this)
|
||||||
val endOffset = tree.getEndOffset(this)
|
val endOffset = tree.getEndOffset(this)
|
||||||
@@ -169,17 +167,12 @@ abstract class BaseConverter(
|
|||||||
return getChildrenAsArray().firstOrNull()
|
return getChildrenAsArray().firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
|
||||||
protected inline fun LighterASTNode.forEachChildren(vararg skipTokens: KtToken, f: (LighterASTNode) -> Unit) {
|
protected inline fun LighterASTNode.forEachChildren(vararg skipTokens: KtToken, f: (LighterASTNode) -> Unit) {
|
||||||
val kidsArray = this.getChildrenAsArray()
|
val kidsArray = this.getChildrenAsArray()
|
||||||
for (kid in kidsArray) {
|
for (kid in kidsArray) {
|
||||||
if (kid == null) break
|
if (kid == null) break
|
||||||
val tokenType = kid.tokenType
|
val tokenType = kid.tokenType
|
||||||
if (COMMENTS.contains(tokenType) || tokenType == WHITE_SPACE || tokenType == SEMICOLON || tokenType in skipTokens) continue
|
if (COMMENTS.contains(tokenType) || tokenType == WHITE_SPACE || tokenType == SEMICOLON || tokenType in skipTokens || tokenType == TokenType.ERROR_ELEMENT) continue
|
||||||
if (tokenType == TokenType.ERROR_ELEMENT) {
|
|
||||||
reportSyntaxError(kid)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f(kid)
|
f(kid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,11 +184,7 @@ abstract class BaseConverter(
|
|||||||
for (kid in kidsArray) {
|
for (kid in kidsArray) {
|
||||||
if (kid == null) break
|
if (kid == null) break
|
||||||
val tokenType = kid.tokenType
|
val tokenType = kid.tokenType
|
||||||
if (COMMENTS.contains(tokenType) || tokenType == WHITE_SPACE || tokenType == SEMICOLON) continue
|
if (COMMENTS.contains(tokenType) || tokenType == WHITE_SPACE || tokenType == SEMICOLON || tokenType == TokenType.ERROR_ELEMENT) continue
|
||||||
if (tokenType == TokenType.ERROR_ELEMENT) {
|
|
||||||
reportSyntaxError(kid)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f(kid, container)
|
f(kid, container)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-17
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.fir.lightTree.converter
|
package org.jetbrains.kotlin.fir.lightTree.converter
|
||||||
|
|
||||||
import com.intellij.lang.LighterASTNode
|
import com.intellij.lang.LighterASTNode
|
||||||
import com.intellij.lang.impl.PsiBuilderImpl
|
|
||||||
import com.intellij.psi.TokenType
|
import com.intellij.psi.TokenType
|
||||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||||
import org.jetbrains.kotlin.*
|
import org.jetbrains.kotlin.*
|
||||||
@@ -19,9 +18,6 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticContext
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.builder.*
|
import org.jetbrains.kotlin.fir.builder.*
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
@@ -40,7 +36,6 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
|||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.*
|
import org.jetbrains.kotlin.fir.lightTree.fir.*
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier
|
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier
|
||||||
@@ -70,22 +65,10 @@ class DeclarationsConverter(
|
|||||||
internal val baseScopeProvider: FirScopeProvider,
|
internal val baseScopeProvider: FirScopeProvider,
|
||||||
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||||
context: Context<LighterASTNode> = Context(),
|
context: Context<LighterASTNode> = Context(),
|
||||||
private val diagnosticsReporter: DiagnosticReporter? = null,
|
|
||||||
private val diagnosticContext: DiagnosticContext? = null,
|
|
||||||
) : BaseConverter(session, tree, context) {
|
) : BaseConverter(session, tree, context) {
|
||||||
|
|
||||||
private val expressionConverter = ExpressionsConverter(session, tree, this, context)
|
private val expressionConverter = ExpressionsConverter(session, tree, this, context)
|
||||||
|
|
||||||
override fun reportSyntaxError(node: LighterASTNode) {
|
|
||||||
val message = PsiBuilderImpl.getErrorMessage(node)
|
|
||||||
diagnosticsReporter?.reportOn(
|
|
||||||
node.toFirSourceElement(),
|
|
||||||
FirSyntaxErrors.SYNTAX,
|
|
||||||
message ?: "Unspecified",
|
|
||||||
diagnosticContext!!,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [org.jetbrains.kotlin.parsing.KotlinParsing.parseFile]
|
* [org.jetbrains.kotlin.parsing.KotlinParsing.parseFile]
|
||||||
* [org.jetbrains.kotlin.parsing.KotlinParsing.parsePreamble]
|
* [org.jetbrains.kotlin.parsing.KotlinParsing.parsePreamble]
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ class TotalKotlinTest : AbstractRawFirBuilderTestCase() {
|
|||||||
text: CharSequence, sourceFile: KtSourceFile, linesMapping: KtSourceFileLinesMapping
|
text: CharSequence, sourceFile: KtSourceFile, linesMapping: KtSourceFileLinesMapping
|
||||||
) {
|
) {
|
||||||
if (onlyLightTree) {
|
if (onlyLightTree) {
|
||||||
val lightTree = LightTree2Fir.buildLightTree(text)
|
val lightTree = LightTree2Fir.buildLightTree(text, null)
|
||||||
DebugUtil.lightTreeToString(lightTree, false)
|
DebugUtil.lightTreeToString(lightTree, false)
|
||||||
} else {
|
} else {
|
||||||
val firFile = converter.buildFirFile(text, sourceFile, linesMapping)
|
val firFile = converter.buildFirFile(text, sourceFile, linesMapping)
|
||||||
|
|||||||
+12
-4
@@ -9,6 +9,8 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.vfs.StandardFileSystems
|
import com.intellij.openapi.vfs.StandardFileSystems
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import org.jetbrains.kotlin.KtInMemoryTextSourceFile
|
import org.jetbrains.kotlin.KtInMemoryTextSourceFile
|
||||||
|
import org.jetbrains.kotlin.KtSourceFile
|
||||||
|
import org.jetbrains.kotlin.fir.lightTree.LightTreeParsingErrorListener
|
||||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.sourceFiles.LightTreeFile
|
import org.jetbrains.kotlin.sourceFiles.LightTreeFile
|
||||||
@@ -110,20 +112,26 @@ fun SourceFileProvider.getKtFilesForSourceFiles(testFiles: Collection<TestFile>,
|
|||||||
}.toMap()
|
}.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SourceFileProvider.getLightTreeKtFileForSourceFile(testFile: TestFile): LightTreeFile {
|
fun SourceFileProvider.getLightTreeKtFileForSourceFile(
|
||||||
|
testFile: TestFile,
|
||||||
|
errorListener: (KtSourceFile) -> LightTreeParsingErrorListener?
|
||||||
|
): LightTreeFile {
|
||||||
val shortName = testFile.toLightTreeShortName()
|
val shortName = testFile.toLightTreeShortName()
|
||||||
val sourceFile = KtInMemoryTextSourceFile(shortName, "/$shortName", getContentOfSourceFile(testFile))
|
val sourceFile = KtInMemoryTextSourceFile(shortName, "/$shortName", getContentOfSourceFile(testFile))
|
||||||
val linesMapping = sourceFile.text.toSourceLinesMapping()
|
val linesMapping = sourceFile.text.toSourceLinesMapping()
|
||||||
val lightTree = LightTree2Fir.buildLightTree(sourceFile.text)
|
val lightTree = LightTree2Fir.buildLightTree(sourceFile.text, errorListener(sourceFile))
|
||||||
return LightTreeFile(lightTree, sourceFile, linesMapping)
|
return LightTreeFile(lightTree, sourceFile, linesMapping)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TestFile.toLightTreeShortName() = name.substringAfterLast('/').substringAfterLast('\\')
|
fun TestFile.toLightTreeShortName() = name.substringAfterLast('/').substringAfterLast('\\')
|
||||||
|
|
||||||
fun SourceFileProvider.getLightTreeFilesForSourceFiles(testFiles: Collection<TestFile>): Map<TestFile, LightTreeFile> {
|
fun SourceFileProvider.getLightTreeFilesForSourceFiles(
|
||||||
|
testFiles: Collection<TestFile>,
|
||||||
|
errorListener: (KtSourceFile) -> LightTreeParsingErrorListener?
|
||||||
|
): Map<TestFile, LightTreeFile> {
|
||||||
return testFiles.mapNotNull {
|
return testFiles.mapNotNull {
|
||||||
if (!it.isKtFile) return@mapNotNull null
|
if (!it.isKtFile) return@mapNotNull null
|
||||||
it to getLightTreeKtFileForSourceFile(it)
|
it to getLightTreeKtFileForSourceFile(it, errorListener)
|
||||||
}.toMap()
|
}.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ fun foo(@<!UNRESOLVED_REFERENCE!>varargs<!> f : Int) {}
|
|||||||
var bar : Int = 1
|
var bar : Int = 1
|
||||||
set(@<!UNRESOLVED_REFERENCE!>varargs<!> v) {}
|
set(@<!UNRESOLVED_REFERENCE!>varargs<!> v) {}
|
||||||
|
|
||||||
val x : (Int) -> Int = <!INITIALIZER_TYPE_MISMATCH{LT}!>{@<!UNRESOLVED_REFERENCE!>varargs<!> x <!SYNTAX!>: Int -> x<!>}<!>
|
val x : (Int) -> Int = {@<!UNRESOLVED_REFERENCE!>varargs<!> x <!SYNTAX!>: Int -> x<!>}
|
||||||
|
|
||||||
class Hello(@<!UNRESOLVED_REFERENCE!>varargs<!> args: Any) {
|
class Hello(@<!UNRESOLVED_REFERENCE!>varargs<!> args: Any) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ fun foo(@test f : Int) {}
|
|||||||
var bar : Int = 1
|
var bar : Int = 1
|
||||||
set(@test v) {}
|
set(@test v) {}
|
||||||
|
|
||||||
val x : (Int) -> Int = <!INITIALIZER_TYPE_MISMATCH{LT}!>{@test x <!SYNTAX!>: Int -> x<!>}<!> // todo fix parser annotation on lambda parameter
|
val x : (Int) -> Int = {@test x <!SYNTAX!>: Int -> x<!>} // todo fix parser annotation on lambda parameter
|
||||||
|
|
||||||
class Hello(@test args: Any) {
|
class Hello(@test args: Any) {
|
||||||
}
|
}
|
||||||
|
|||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
// COMPARE_WITH_LIGHT_TREE
|
|
||||||
package h
|
|
||||||
|
|
||||||
class Square() {
|
|
||||||
var size : Double =
|
|
||||||
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {
|
|
||||||
//in LT this LAMBDA_EXPRESSION get parsed lazyly, but doesn't got anywhere in FIR tree (as property doesn't have place for it)
|
|
||||||
<!SYNTAX{PSI}!>$area<!> <!SYNTAX{PSI}!>= size * size<!>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var area : Double<!>
|
|
||||||
private set
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
val s = Square()
|
|
||||||
|
|
||||||
s.size = 2.0
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1,10 +1,10 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// COMPARE_WITH_LIGHT_TREE
|
// COMPARE_WITH_LIGHT_TREE
|
||||||
package h
|
package h
|
||||||
|
|
||||||
class Square() {
|
class Square() {
|
||||||
var size : Double =
|
var size : Double =
|
||||||
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {
|
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {
|
||||||
//in LT this LAMBDA_EXPRESSION get parsed lazyly, but doesn't got anywhere in FIR tree (as property doesn't have place for it)
|
|
||||||
<!SYNTAX!>$area<!> <!SYNTAX!>= size * size<!>
|
<!SYNTAX!>$area<!> <!SYNTAX!>= size * size<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ fun sum(a : IntArray) : Int {
|
|||||||
<!UNRESOLVED_REFERENCE!>res<!> = 0
|
<!UNRESOLVED_REFERENCE!>res<!> = 0
|
||||||
for (e in a)
|
for (e in a)
|
||||||
<!UNRESOLVED_REFERENCE!>res<!> +=<!SYNTAX!><!>
|
<!UNRESOLVED_REFERENCE!>res<!> +=<!SYNTAX!><!>
|
||||||
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY{LT}!>}<!>
|
}
|
||||||
fun main() {
|
fun main() {
|
||||||
test(0)
|
test(0)
|
||||||
test(1, 1)
|
test(1, 1)
|
||||||
|
|||||||
@@ -25,5 +25,5 @@ val z = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>z<!>
|
|||||||
fun block(f : () -> Unit) = f()
|
fun block(f : () -> Unit) = f()
|
||||||
|
|
||||||
fun bar3() = block{ <!UNRESOLVED_REFERENCE!>foo3<!>() // <-- missing closing curly bracket
|
fun bar3() = block{ <!UNRESOLVED_REFERENCE!>foo3<!>() // <-- missing closing curly bracket
|
||||||
fun foo3() = block{ <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar3()<!> }<!SYNTAX{PSI}!><!>
|
fun foo3() = block{ <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar3()<!> }<!SYNTAX!><!>
|
||||||
|
|
||||||
|
|||||||
+9
-1
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
|||||||
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
|
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||||
|
import org.jetbrains.kotlin.fir.lightTree.toKotlinParsingErrorListener
|
||||||
import org.jetbrains.kotlin.fir.session.FirCommonSessionFactory
|
import org.jetbrains.kotlin.fir.session.FirCommonSessionFactory
|
||||||
import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory
|
import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory
|
||||||
import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory
|
import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory
|
||||||
@@ -283,7 +284,14 @@ open class FirFrontendFacade(
|
|||||||
val parser = module.directives.singleValue(FirDiagnosticsDirectives.FIR_PARSER)
|
val parser = module.directives.singleValue(FirDiagnosticsDirectives.FIR_PARSER)
|
||||||
|
|
||||||
val (ktFiles, lightTreeFiles) = when (parser) {
|
val (ktFiles, lightTreeFiles) = when (parser) {
|
||||||
FirParser.LightTree -> emptyList<KtFile>() to testServices.sourceFileProvider.getLightTreeFilesForSourceFiles(module.files).values
|
FirParser.LightTree -> {
|
||||||
|
emptyList<KtFile>() to testServices.sourceFileProvider.getLightTreeFilesForSourceFiles(module.files) {
|
||||||
|
testServices.lightTreeSyntaxDiagnosticsReporterHolder?.reporter?.toKotlinParsingErrorListener(
|
||||||
|
it,
|
||||||
|
module.languageVersionSettings
|
||||||
|
)
|
||||||
|
}.values
|
||||||
|
}
|
||||||
FirParser.Psi -> testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList()
|
FirParser.Psi -> testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class LightTreeParsingTest {
|
|||||||
val (code, mapping) = ByteArrayInputStream(toByteArray()).reader().readSourceFileWithMapping()
|
val (code, mapping) = ByteArrayInputStream(toByteArray()).reader().readSourceFileWithMapping()
|
||||||
val positionFinder = SequentialPositionFinder(ByteArrayInputStream(toByteArray()).reader())
|
val positionFinder = SequentialPositionFinder(ByteArrayInputStream(toByteArray()).reader())
|
||||||
val linePositions =
|
val linePositions =
|
||||||
LightTree2Fir.buildLightTree(code).getChildrenAsArray()
|
LightTree2Fir.buildLightTree(code, null).getChildrenAsArray()
|
||||||
.mapNotNull { it?.startOffset }
|
.mapNotNull { it?.startOffset }
|
||||||
.map {
|
.map {
|
||||||
val nextPos = positionFinder.findNextPosition(it)
|
val nextPos = positionFinder.findNextPosition(it)
|
||||||
|
|||||||
Reference in New Issue
Block a user