Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{kt,kts}]
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
ij_kotlin_imports_layout = *
7 changes: 1 addition & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ spotless {
kotlin {
target "**/*.kt"
targetExclude "**/gen/**/*.*"
ktlint('0.49.1').editorConfigOverride([
"indent_size": "2",
"disabled_rules": "package-name",
"ij_kotlin_allow_trailing_comma": "true",
"ij_kotlin_allow_trailing_comma_on_call_site": "true",
])
ktfmt(libs.ktfmt.get().version).googleStyle()
trimTrailingWhitespace()
endWithNewline()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package com.alecstrong.sql.psi.core
import com.intellij.psi.PsiFile
import java.util.concurrent.atomic.AtomicReference

class ModifiableFileLazy<out T>(
private val initializer: () -> T,
) {
class ModifiableFileLazy<out T>(private val initializer: () -> T) {
private var modifiedStamp = -1L
private var state = AtomicReference<T>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ import com.intellij.lang.parser.GeneratedParserUtilBase

abstract class ModuleParserUtil : GeneratedParserUtilBase() {
companion object {
@JvmStatic fun custom_module_argument(builder: PsiBuilder, level: Int, columnName: Parser): Boolean {
if (!GeneratedParserUtilBase.recursion_guard_(builder, level, "module_argument_real")) return false
@JvmStatic
fun custom_module_argument(builder: PsiBuilder, level: Int, columnName: Parser): Boolean {
if (!GeneratedParserUtilBase.recursion_guard_(builder, level, "module_argument_real"))
return false
var result: Boolean
val marker = GeneratedParserUtilBase.enter_section_(
builder,
level,
GeneratedParserUtilBase._COLLAPSE_,
MODULE_ARGUMENT,
"<module argument real>",
)
val marker =
GeneratedParserUtilBase.enter_section_(
builder,
level,
GeneratedParserUtilBase._COLLAPSE_,
MODULE_ARGUMENT,
"<module argument real>",
)
columnName.parse(builder, level + 1)
var parens = 0
while (builder.tokenType != SqlTypes.COMMA) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ open class SqlAnnotator : Annotator {
}
}

class AnnotationException(val msg: String, val element: PsiElement? = null) : IllegalStateException(msg)
class AnnotationException(val msg: String, val element: PsiElement? = null) :
IllegalStateException(msg)

fun interface SqlAnnotationHolder {
fun createErrorAnnotation(element: PsiElement, message: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class SqlElementType(name: String) : IElementType(name, null) {
abstract class SqlSchemaContributorElementType<SchemaType : SchemaContributor>(
private val name: String,
/**
* This should be the same class used when interfacing with [com.alecstrong.sql.psi.core.psi.Schema]
* This should be the same class used when interfacing with
* [com.alecstrong.sql.psi.core.psi.Schema]
*/
private val schemaClass: Class<SchemaType>,
) : ILightStubElementType<SchemaContributorStub, SchemaContributor>(name, null) {
Expand Down
43 changes: 22 additions & 21 deletions core/src/main/kotlin/com/alecstrong/sql/psi/core/SqlFileBase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import kotlin.reflect.KClass

abstract class SqlFileBase(
viewProvider: FileViewProvider,
language: Language,
) : PsiFileBase(viewProvider, language) {
abstract class SqlFileBase(viewProvider: FileViewProvider, language: Language) :
PsiFileBase(viewProvider, language) {
abstract val order: Long?

val sqlStmtList
get() = findChildByClass(SqlStmtList::class.java)

fun tablesAvailable(child: PsiElement) = schema<TableElement>(child).map { it.tableExposed() }

fun triggers(sqlStmtElement: PsiElement?): Collection<SqlCreateTriggerStmt> = schema(sqlStmtElement)
fun triggers(sqlStmtElement: PsiElement?): Collection<SqlCreateTriggerStmt> =
schema(sqlStmtElement)

internal inline fun <reified T : SchemaContributor> schema(
sqlStmtElement: PsiElement? = null,
Expand Down Expand Up @@ -62,29 +61,31 @@ abstract class SqlFileBase(
}

/**
* @return Tables this file exposes as LazyQuery.
*
* @param includeAll If true, also return tables that other files expose.
* @return Tables this file exposes as LazyQuery.
*/
fun tables(includeAll: Boolean): Collection<LazyQuery> {
val tables = schema<TableElement>().map { it.tableExposed() }
return if (includeAll) tables else tables.filter { it.tableName.containingFile == this }
}

internal fun viewForName(name: String): SqlCreateViewStmt? {
return schema<TableElement>().filterIsInstance<SqlCreateViewStmt>().singleOrNull { it.name() == name }
return schema<TableElement>().filterIsInstance<SqlCreateViewStmt>().singleOrNull {
it.name() == name
}
}

private fun views(): List<SqlCreateViewStmt> {
return sqlStmtList?.stmtList?.mapNotNull {
it.createViewStmt
}.orEmpty()
return sqlStmtList?.stmtList?.mapNotNull { it.createViewStmt }.orEmpty()
}

private fun tables(): List<TableElement> {
return sqlStmtList?.stmtList?.mapNotNull {
(it.createViewStmt as TableElement?) ?: it.createTableStmt ?: it.createVirtualTableStmt
}.orEmpty()
return sqlStmtList
?.stmtList
?.mapNotNull {
(it.createViewStmt as TableElement?) ?: it.createTableStmt ?: it.createVirtualTableStmt
}
.orEmpty()
}

private inline fun <T : SchemaContributor> iteratePreviousStatements(
Expand Down Expand Up @@ -127,17 +128,17 @@ abstract class SqlFileBase(
topContributors.forEach(block)
}

contributors()?.takeWhile { order == null || until == null || it.textOffset <= until.textOffset }
?.forEach {
block(it)
}
contributors()
?.takeWhile { order == null || until == null || it.textOffset <= until.textOffset }
?.forEach { block(it) }
}

private fun contributors() = sqlStmtList?.stmtList?.mapNotNull { it.firstChild as? SchemaContributor }
private fun contributors() =
sqlStmtList?.stmtList?.mapNotNull { it.firstChild as? SchemaContributor }

/**
* Optional files which can be used for extra Schema Contributors that are unindexed.
* The files are added to the schema in the provided order.
* Optional files which can be used for extra Schema Contributors that are unindexed. The files
* are added to the schema in the provided order.
*/
protected open fun baseContributorFiles(): List<SqlFileBase> = emptyList()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@ abstract class SqlParserDefinition : ParserDefinition {
}

override fun createLexer(project: Project): Lexer = SqlLexerAdapter()

override fun getWhitespaceTokens() = WHITE_SPACES

override fun getCommentTokens() = COMMENTS

override fun getStringLiteralElements(): TokenSet = TokenSet.EMPTY

override fun spaceExistenceTypeBetweenTokens(p0: ASTNode, p1: ASTNode) = MAY

override fun createElement(node: ASTNode): PsiElement = SqlParserUtil.createElement(node)

override fun createParser(project: Project) = SqlParser()

abstract override fun createFile(viewProvider: FileViewProvider): SqlFileBase

abstract fun getLanguage(): Language
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,30 @@ interface AlterTableApplier : PsiElement {
}

val AlterTableApplier.alterStmt
get() = PsiTreeUtil.getParentOfType(
this,
SqlAlterTableStmt::class.java,
)!!
get() = PsiTreeUtil.getParentOfType(this, SqlAlterTableStmt::class.java)!!

internal fun LazyQuery.withAlterStatement(
alter: SqlAlterTableStmt,
until: SqlAlterTableRules? = null,
): LazyQuery {
return alter.alterTableRulesList.takeWhile { it != until }.fold(
this,
{ lazyQuery, alterTableRules ->
// Rename table.
alterTableRules.alterTableRenameTable?.let { renameTable ->
return@fold LazyQuery(
tableName = renameTable.newTableName,
query = {
lazyQuery.query.copy(table = renameTable.newTableName)
},
)
}
return alter.alterTableRulesList
.takeWhile { it != until }
.fold(
this,
{ lazyQuery, alterTableRules ->
// Rename table.
alterTableRules.alterTableRenameTable?.let { renameTable ->
return@fold LazyQuery(
tableName = renameTable.newTableName,
query = { lazyQuery.query.copy(table = renameTable.newTableName) },
)
}

(alterTableRules.firstChild as? AlterTableApplier)?.let {
return@fold it.applyTo(lazyQuery)
}
(alterTableRules.firstChild as? AlterTableApplier)?.let {
return@fold it.applyTo(lazyQuery)
}

return@fold lazyQuery
},
)
return@fold lazyQuery
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@ interface QueryElement : PsiElement {
/**
* Return all of the results that this query exposes. The select_stmt rule
*
* SELECT *
* FROM a_table;
* ```
* SELECT *
* FROM a_table;
* ```
*
* Would expose [QueryResults(a_table, [all of a_tables columns])]
* Would expose `[QueryResults(a_table, [all of a_tables columns])]`
*
* The join_clause rule
*
* a_table JOIN a_second_table
* ```
* a_table JOIN a_second_table
* ```
*
* Would expose [QueryResult(a_table, [all of a_tables columns]), QueryResult(a_second_table, [all of a_second_tables columns])]
* Would expose `[QueryResult(a_table, [all of a_tables columns]), QueryResult(a_second_table,
* [all of a_second_tables columns])]`
*/
fun queryExposed(): Collection<QueryResult>

Expand Down Expand Up @@ -51,8 +56,8 @@ interface QueryElement : PsiElement {
)

/**
* These aren't considered part of the exposed query (ie performing a SELECT * does not return
* the column in the result set) but they can be explicitly referenced.
* These aren't considered part of the exposed query (ie performing a SELECT * does not return the
* column in the result set) but they can be explicitly referenced.
*/
data class SynthesizedColumn(
val table: PsiElement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import kotlin.reflect.KClass

interface SchemaContributor : SqlCompositeElement {
fun modifySchema(schema: Schema)

fun name(): String
}

interface SchemaContributorStub : StubElement<SchemaContributor> {
fun name(): String

fun getTextOffset(): Int
}

Expand All @@ -20,22 +22,25 @@ internal open class SchemaContributorStubImpl<T : SchemaContributor>(
type: SqlSchemaContributorElementType<T>,
private val name: String,
private val textOffset: Int,
) : StubBase<SchemaContributor>(parent, type),
SchemaContributorStub {
) : StubBase<SchemaContributor>(parent, type), SchemaContributorStub {
override fun name() = name

override fun getTextOffset() = textOffset
}

class Schema {
private val map = mutableMapOf<KClass<out SchemaContributor>, MutableMap<String, out SchemaContributor>>()
private val map =
mutableMapOf<KClass<out SchemaContributor>, MutableMap<String, out SchemaContributor>>()

@Suppress("UNCHECKED_CAST")
internal inline fun <reified Value : SchemaContributor> forType(): MutableMap<String, Value> =
map.getOrPut(Value::class, { linkedMapOf<String, Value>() }) as MutableMap<String, Value>

@Suppress("UNCHECKED_CAST")
internal inline fun <reified Value : SchemaContributor> put(value: SchemaContributor) {
val map = map.getOrPut(Value::class, { linkedMapOf<String, Value>() }) as MutableMap<String, SchemaContributor>
val map =
map.getOrPut(Value::class, { linkedMapOf<String, Value>() })
as MutableMap<String, SchemaContributor>
map.putIfAbsent(value.name(), value)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import com.intellij.psi.stubs.StubIndexKey

interface SchemaContributorIndex {
fun getKey(): StubIndexKey<String, SchemaContributor>

fun get(key: String, project: Project, scope: GlobalSearchScope): Collection<SchemaContributor>

companion object {
val KEY by lazy {
StubIndexKey.createIndexKey<String, SchemaContributor>("sqldelight.schema")
}
val KEY by lazy { StubIndexKey.createIndexKey<String, SchemaContributor>("sqldelight.schema") }

fun getInstance(project: Project): SchemaContributorIndex {
return project.serviceOrNull() ?: SchemaContributorIndexImpl.instance
}
}
}

internal class SchemaContributorIndexImpl : SchemaContributorIndex, StringStubIndexExtension<SchemaContributor>() {
internal class SchemaContributorIndexImpl :
SchemaContributorIndex, StringStubIndexExtension<SchemaContributor>() {
override fun getVersion() = 4

override fun getKey(): StubIndexKey<String, SchemaContributor> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import com.alecstrong.sql.psi.core.SqlAnnotationHolder
import com.intellij.psi.PsiElement

interface SqlAnnotatedElement : PsiElement {
/**
* Called by the annotator to annotate this element with any errors or warnings.
*/
/** Called by the annotator to annotate this element with any errors or warnings. */
fun annotate(annotationHolder: SqlAnnotationHolder)
}
Loading