New J2K: Add repeatable post processing groups
This commit is contained in:
committed by
Ilya Kirillov
parent
c827247272
commit
9c71d5ca25
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.nj2k
|
package org.jetbrains.kotlin.nj2k
|
||||||
|
|
||||||
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
|
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
@@ -24,13 +24,13 @@ import com.intellij.openapi.util.TextRange
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
import kotlinx.coroutines.experimental.withContext
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
import org.jetbrains.kotlin.idea.conversion.copy.range
|
import org.jetbrains.kotlin.idea.conversion.copy.range
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
|
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessing
|
||||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
@@ -63,49 +63,48 @@ class NewJ2kPostProcessor(
|
|||||||
PROCESS
|
PROCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun List<NewJ2kPostProcessing>.runProcessings(file: KtFile, rangeMarker: RangeMarker?): Boolean {
|
||||||
|
var modificationStamp: Long? = file.modificationStamp
|
||||||
|
val elementToActions = runReadAction {
|
||||||
|
collectAvailableActions(this, file, rangeMarker)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((element, action, _, writeActionNeeded) in elementToActions) {
|
||||||
|
if (element.isValid) {
|
||||||
|
if (writeActionNeeded) {
|
||||||
|
runWriteAction {
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
modificationStamp = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modificationStamp != file.modificationStamp && elementToActions.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Processing.runProcessings(file: KtFile, rangeMarker: RangeMarker?) {
|
||||||
|
when (this) {
|
||||||
|
is SingleOneTimeProcessing -> listOf(processing).runProcessings(file, rangeMarker)
|
||||||
|
is RepeatableProcessingGroup ->
|
||||||
|
do {
|
||||||
|
val needContinue = processings.runProcessings(file, rangeMarker)
|
||||||
|
} while (needContinue)
|
||||||
|
is OneTimeProcessingGroup ->
|
||||||
|
processings.forEach { it.runProcessings(file, rangeMarker) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun doAdditionalProcessing(file: KtFile, rangeMarker: RangeMarker?) {
|
override fun doAdditionalProcessing(file: KtFile, rangeMarker: RangeMarker?) {
|
||||||
fun Processing.flattenToGroups(): List<List<NewJ2kPostProcessing>> =
|
|
||||||
when (this) {
|
|
||||||
is SingleProcessing -> listOf(listOf(this.processing))
|
|
||||||
is ProcessingGroup ->
|
|
||||||
if (processings.all { it is SingleProcessing }) {
|
|
||||||
listOf(processings.map { (it as SingleProcessing).processing })
|
|
||||||
} else {
|
|
||||||
processings.flatMap { it.flattenToGroups() }
|
|
||||||
}
|
|
||||||
else -> error("Processing tree is corrupted")
|
|
||||||
}
|
|
||||||
OptimizeImportsProcessor(file.project, file.containingKtFile).run()
|
OptimizeImportsProcessor(file.project, file.containingKtFile).run()
|
||||||
val groupsOfProcessings = NewJ2KPostProcessingRegistrar.mainProcessings.flattenToGroups()
|
|
||||||
|
|
||||||
runBlocking(EDT.ModalityStateElement(ModalityState.defaultModalityState())) {
|
runBlocking(EDT.ModalityStateElement(ModalityState.defaultModalityState())) {
|
||||||
for (processings in groupsOfProcessings) {
|
NewJ2KPostProcessingRegistrar.mainProcessings.runProcessings(file, rangeMarker)
|
||||||
do {
|
|
||||||
var modificationStamp: Long? = file.modificationStamp
|
|
||||||
val elementToActions = runReadAction {
|
|
||||||
collectAvailableActions(processings, file, rangeMarker)
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(EDT) {
|
|
||||||
for ((element, action, _, writeActionNeeded) in elementToActions) {
|
|
||||||
if (element.isValid) {
|
|
||||||
if (writeActionNeeded) {
|
|
||||||
runWriteAction {
|
|
||||||
action()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
action()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
modificationStamp = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modificationStamp == file.modificationStamp) break
|
|
||||||
} while (elementToActions.isNotEmpty())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formatCode) {
|
if (formatCode) {
|
||||||
withContext(EDT) {
|
withContext(EDT) {
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.nj2k
|
package org.jetbrains.kotlin.nj2k
|
||||||
|
|
||||||
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
|
|
||||||
import com.intellij.codeInspection.*
|
import com.intellij.codeInspection.*
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiDocumentManager
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.search.LocalSearchScope
|
import com.intellij.psi.search.LocalSearchScope
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
@@ -65,8 +63,12 @@ interface NewJ2kPostProcessing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Processing
|
interface Processing
|
||||||
data class SingleProcessing(val processing: NewJ2kPostProcessing) : Processing
|
data class SingleOneTimeProcessing(val processing: NewJ2kPostProcessing) : Processing
|
||||||
data class ProcessingGroup(val processings: List<Processing>) : Processing {
|
data class RepeatableProcessingGroup(val processings: List<NewJ2kPostProcessing>) : Processing {
|
||||||
|
constructor(vararg processings: NewJ2kPostProcessing) : this(processings.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
data class OneTimeProcessingGroup(val processings: List<Processing>) : Processing {
|
||||||
constructor(vararg processings: Processing) : this(processings.toList())
|
constructor(vararg processings: Processing) : this(processings.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,8 +76,9 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
|
|
||||||
private fun Processing.processings(): Sequence<NewJ2kPostProcessing> =
|
private fun Processing.processings(): Sequence<NewJ2kPostProcessing> =
|
||||||
when (this) {
|
when (this) {
|
||||||
is SingleProcessing -> sequenceOf(processing)
|
is SingleOneTimeProcessing -> sequenceOf(processing)
|
||||||
is ProcessingGroup -> processings.asSequence().flatMap { it.processings() }
|
is RepeatableProcessingGroup -> processings.asSequence()
|
||||||
|
is OneTimeProcessingGroup -> processings.asSequence().flatMap { it.processings() }
|
||||||
else -> sequenceOf()
|
else -> sequenceOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,49 +87,46 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
|
|
||||||
fun priority(processing: NewJ2kPostProcessing): Int = processingsToPriorityMap[processing]!!
|
fun priority(processing: NewJ2kPostProcessing): Int = processingsToPriorityMap[processing]!!
|
||||||
|
|
||||||
val mainProcessings = ProcessingGroup(
|
val mainProcessings = OneTimeProcessingGroup(
|
||||||
SingleProcessing(VarToVal()),
|
SingleOneTimeProcessing(VarToVal()),
|
||||||
ProcessingGroup(
|
SingleOneTimeProcessing(ConvertGettersAndSetters()),
|
||||||
SingleProcessing(ConvertGettersAndSetters()),
|
SingleOneTimeProcessing(registerGeneralInspectionBasedProcessing(RedundantModalityModifierInspection())),
|
||||||
registerGeneralInspectionBasedProcessing(RedundantModalityModifierInspection()),
|
SingleOneTimeProcessing(registerGeneralInspectionBasedProcessing(RedundantVisibilityModifierInspection())),
|
||||||
registerGeneralInspectionBasedProcessing(RedundantVisibilityModifierInspection()),
|
SingleOneTimeProcessing(registerGeneralInspectionBasedProcessing(RedundantGetterInspection())),
|
||||||
registerGeneralInspectionBasedProcessing(RedundantGetterInspection()),
|
SingleOneTimeProcessing(registerGeneralInspectionBasedProcessing(RedundantSetterInspection())),
|
||||||
registerGeneralInspectionBasedProcessing(RedundantSetterInspection())
|
SingleOneTimeProcessing(ConvertDataClass()),
|
||||||
),
|
RepeatableProcessingGroup(
|
||||||
SingleProcessing(ConvertDataClass()),
|
|
||||||
ProcessingGroup(
|
|
||||||
registerGeneralInspectionBasedProcessing(ExplicitThisInspection()),
|
registerGeneralInspectionBasedProcessing(ExplicitThisInspection()),
|
||||||
|
RemoveExplicitTypeArgumentsProcessing(),
|
||||||
SingleProcessing(RemoveExplicitTypeArgumentsProcessing()),
|
RemoveRedundantOverrideVisibilityProcessing(),
|
||||||
SingleProcessing(RemoveRedundantOverrideVisibilityProcessing()),
|
|
||||||
registerInspectionBasedProcessing(MoveLambdaOutsideParenthesesInspection()),
|
registerInspectionBasedProcessing(MoveLambdaOutsideParenthesesInspection()),
|
||||||
registerGeneralInspectionBasedProcessing(RedundantCompanionReferenceInspection()),
|
registerGeneralInspectionBasedProcessing(RedundantCompanionReferenceInspection()),
|
||||||
SingleProcessing(FixObjectStringConcatenationProcessing()),
|
FixObjectStringConcatenationProcessing(),
|
||||||
SingleProcessing(ConvertToStringTemplateProcessing()),
|
ConvertToStringTemplateProcessing(),
|
||||||
SingleProcessing(UsePropertyAccessSyntaxProcessing()),
|
UsePropertyAccessSyntaxProcessing(),
|
||||||
SingleProcessing(UninitializedVariableReferenceFromInitializerToThisReferenceProcessing()),
|
UninitializedVariableReferenceFromInitializerToThisReferenceProcessing(),
|
||||||
SingleProcessing(UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing()),
|
UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing(),
|
||||||
SingleProcessing(RemoveRedundantSamAdaptersProcessing()),
|
RemoveRedundantSamAdaptersProcessing(),
|
||||||
SingleProcessing(RemoveRedundantCastToNullableProcessing()),
|
RemoveRedundantCastToNullableProcessing(),
|
||||||
registerInspectionBasedProcessing(ReplacePutWithAssignmentInspection()),
|
registerInspectionBasedProcessing(ReplacePutWithAssignmentInspection()),
|
||||||
SingleProcessing(UseExpressionBodyProcessing()),
|
UseExpressionBodyProcessing(),
|
||||||
registerInspectionBasedProcessing(UnnecessaryVariableInspection()),
|
registerInspectionBasedProcessing(UnnecessaryVariableInspection()),
|
||||||
SingleProcessing(
|
|
||||||
object : NewJ2kPostProcessing {
|
|
||||||
override val writeActionNeeded: Boolean = true
|
|
||||||
private val processing = registerGeneralInspectionBasedProcessing(RedundantExplicitTypeInspection())
|
|
||||||
|
|
||||||
override fun createAction(element: KtElement, diagnostics: Diagnostics, settings: ConverterSettings?): (() -> Unit)? {
|
object : NewJ2kPostProcessing {
|
||||||
if (settings?.specifyLocalVariableTypeByDefault == true) return null
|
override val writeActionNeeded: Boolean = true
|
||||||
|
private val processing = registerGeneralInspectionBasedProcessing(RedundantExplicitTypeInspection())
|
||||||
|
|
||||||
return processing.processing.createAction(element, diagnostics)
|
override fun createAction(element: KtElement, diagnostics: Diagnostics, settings: ConverterSettings?): (() -> Unit)? {
|
||||||
}
|
if (settings?.specifyLocalVariableTypeByDefault == true) return null
|
||||||
|
|
||||||
|
return processing.createAction(element, diagnostics)
|
||||||
}
|
}
|
||||||
),
|
}
|
||||||
|
,
|
||||||
registerGeneralInspectionBasedProcessing(RedundantUnitReturnTypeInspection()),
|
registerGeneralInspectionBasedProcessing(RedundantUnitReturnTypeInspection()),
|
||||||
|
|
||||||
SingleProcessing(RemoveExplicitPropertyType()),
|
RemoveExplicitPropertyType(),
|
||||||
SingleProcessing(RemoveRedundantNullability()),
|
RemoveRedundantNullability(),
|
||||||
|
|
||||||
registerGeneralInspectionBasedProcessing(CanBeValInspection(ignoreNotUsedVals = false)),
|
registerGeneralInspectionBasedProcessing(CanBeValInspection(ignoreNotUsedVals = false)),
|
||||||
|
|
||||||
@@ -142,7 +142,6 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
) as KtReturnExpression).returnedExpression.isTrivialStatementBody()
|
) as KtReturnExpression).returnedExpression.isTrivialStatementBody()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
registerInspectionBasedProcessing(IfThenToSafeAccessInspection()),
|
registerInspectionBasedProcessing(IfThenToSafeAccessInspection()),
|
||||||
registerInspectionBasedProcessing(IfThenToSafeAccessInspection()),
|
registerInspectionBasedProcessing(IfThenToSafeAccessInspection()),
|
||||||
registerIntentionBasedProcessing(IfThenToElvisIntention()),
|
registerIntentionBasedProcessing(IfThenToElvisIntention()),
|
||||||
@@ -170,8 +169,8 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
action.invoke(element.project, null, element.containingKtFile)
|
action.invoke(element.project, null, element.containingKtFile)
|
||||||
},
|
},
|
||||||
|
|
||||||
SingleProcessing(RemoveRedundantTypeQualifierProcessing()),
|
RemoveRedundantTypeQualifierProcessing(),
|
||||||
SingleProcessing(RemoveRedundantExpressionQualifierProcessing()),
|
RemoveRedundantExpressionQualifierProcessing(),
|
||||||
|
|
||||||
registerDiagnosticBasedProcessing<KtBinaryExpressionWithTypeRHS>(Errors.USELESS_CAST) { element, _ ->
|
registerDiagnosticBasedProcessing<KtBinaryExpressionWithTypeRHS>(Errors.USELESS_CAST) { element, _ ->
|
||||||
val expression = RemoveUselessCastFix.invoke(element)
|
val expression = RemoveUselessCastFix.invoke(element)
|
||||||
@@ -215,7 +214,7 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
},
|
},
|
||||||
|
|
||||||
registerDiagnosticBasedProcessingFactory(
|
registerDiagnosticBasedProcessingFactory(
|
||||||
Errors.VAL_REASSIGNMENT, Errors.CAPTURED_VAL_INITIALIZATION, Errors.CAPTURED_MEMBER_VAL_INITIALIZATION
|
Errors.VAL_REASSIGNMENT, Errors.CAPTURED_VAL_INITIALIZATION, Errors.CAPTURED_MEMBER_VAL_INITIALIZATION
|
||||||
) { element: KtSimpleNameExpression, _: Diagnostic ->
|
) { element: KtSimpleNameExpression, _: Diagnostic ->
|
||||||
val property = element.mainReference.resolve() as? KtProperty
|
val property = element.mainReference.resolve() as? KtProperty
|
||||||
if (property == null) {
|
if (property == null) {
|
||||||
@@ -253,7 +252,7 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
private inline fun <reified TElement : KtElement, TIntention : SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
|
private inline fun <reified TElement : KtElement, TIntention : SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
|
||||||
intention: TIntention,
|
intention: TIntention,
|
||||||
noinline additionalChecker: (TElement) -> Boolean = { true }
|
noinline additionalChecker: (TElement) -> Boolean = { true }
|
||||||
) = SingleProcessing(object : NewJ2kPostProcessing {
|
) = object : NewJ2kPostProcessing {
|
||||||
// Intention can either need or not need write action
|
// Intention can either need or not need write action
|
||||||
override val writeActionNeeded = intention.startInWriteAction()
|
override val writeActionNeeded = intention.startInWriteAction()
|
||||||
|
|
||||||
@@ -269,13 +268,12 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
private inline fun <TInspection : AbstractKotlinInspection> registerGeneralInspectionBasedProcessing(
|
private inline fun <TInspection : AbstractKotlinInspection> registerGeneralInspectionBasedProcessing(
|
||||||
inspection: TInspection,
|
inspection: TInspection,
|
||||||
acceptInformationLevel: Boolean = false
|
acceptInformationLevel: Boolean = false
|
||||||
) = SingleProcessing(object : NewJ2kPostProcessing {
|
) = (object : NewJ2kPostProcessing {
|
||||||
override val writeActionNeeded = false
|
override val writeActionNeeded = false
|
||||||
|
|
||||||
fun <D : CommonProblemDescriptor> QuickFix<D>.applyFixSmart(project: Project, descriptor: D) {
|
fun <D : CommonProblemDescriptor> QuickFix<D>.applyFixSmart(project: Project, descriptor: D) {
|
||||||
@@ -347,7 +345,7 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
|
|
||||||
inspection: TInspection,
|
inspection: TInspection,
|
||||||
acceptInformationLevel: Boolean = false
|
acceptInformationLevel: Boolean = false
|
||||||
) = SingleProcessing(object : NewJ2kPostProcessing {
|
) = object : NewJ2kPostProcessing {
|
||||||
// Inspection can either need or not need write action
|
// Inspection can either need or not need write action
|
||||||
override val writeActionNeeded = inspection.startFixInWriteAction
|
override val writeActionNeeded = inspection.startFixInWriteAction
|
||||||
|
|
||||||
@@ -366,27 +364,28 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
private inline fun <reified TElement : KtElement> registerDiagnosticBasedProcessing(
|
private inline fun <reified TElement : KtElement> registerDiagnosticBasedProcessing(
|
||||||
vararg diagnosticFactory: DiagnosticFactory<*>,
|
vararg diagnosticFactory: DiagnosticFactory<*>,
|
||||||
crossinline fix: (TElement, Diagnostic) -> Unit
|
crossinline fix: (TElement, Diagnostic) -> Unit
|
||||||
) = registerDiagnosticBasedProcessingFactory(*diagnosticFactory) { element: TElement, diagnostic: Diagnostic ->
|
) = object : NewJ2kPostProcessing {
|
||||||
{
|
override val writeActionNeeded = true
|
||||||
fix(
|
|
||||||
element,
|
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
diagnostic
|
if (!TElement::class.java.isInstance(element)) return null
|
||||||
)
|
val diagnostic = diagnostics.forElement(element).firstOrNull { it.factory in diagnosticFactory } ?: return null
|
||||||
|
return {
|
||||||
|
fix(element as TElement, diagnostic)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private inline fun <reified TElement : KtElement> registerDiagnosticBasedProcessingFactory(
|
private inline fun <reified TElement : KtElement> registerDiagnosticBasedProcessingFactory(
|
||||||
vararg diagnosticFactory: DiagnosticFactory<*>,
|
vararg diagnosticFactory: DiagnosticFactory<*>,
|
||||||
crossinline fixFactory: (TElement, Diagnostic) -> (() -> Unit)?
|
crossinline fixFactory: (TElement, Diagnostic) -> (() -> Unit)?
|
||||||
) = SingleProcessing(object : NewJ2kPostProcessing {
|
) = object : NewJ2kPostProcessing {
|
||||||
// ???
|
|
||||||
override val writeActionNeeded = true
|
override val writeActionNeeded = true
|
||||||
|
|
||||||
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
|
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
@@ -394,7 +393,7 @@ object NewJ2KPostProcessingRegistrar {
|
|||||||
val diagnostic = diagnostics.forElement(element).firstOrNull { it.factory in diagnosticFactory } ?: return null
|
val diagnostic = diagnostics.forElement(element).firstOrNull { it.factory in diagnosticFactory } ?: return null
|
||||||
return fixFactory(element as TElement, diagnostic)
|
return fixFactory(element as TElement, diagnostic)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
private class RemoveExplicitPropertyType : NewJ2kPostProcessing {
|
private class RemoveExplicitPropertyType : NewJ2kPostProcessing {
|
||||||
|
|||||||
Reference in New Issue
Block a user