How to show IntelliJ JSON editor in dialog? - intellij-idea

I want to show below kind of an editor inside a dialog in an plugin that I'm developing for Kotlin and Java. I tried the below code snippet
editorTextField.setEnabled(true);
editorTextField.setOneLineMode(false);
editorTextField.setFileType(new JsonFileType());
Could someone point out how to achieve this?
Particularly I need the line numbers, JSON syntax highlighting and code folding I can see all the code specifications here. Please help me in learning how can I use them in my plugins.
JSON editor :

class JsonOutputDialog(language: Language, project: Project, text: String) : DialogWrapper(project) {
private val panel = JPanel(BorderLayout())
init {
super.setOKActionEnabled(false)
init()
val editorTextField = CustomEditorField(language, project, text)
editorTextField.setOneLineMode(false)
editorTextField.preferredSize = Dimension(800, 600)
editorTextField.isVisible = true
panel.add(editorTextField)
editorTextField.setCaretPosition(0)
}
override fun createCenterPanel() = panel
}
class CustomEditorField(language: Language, project: Project, s: String) : LanguageTextField(language, project, s) {
override fun createEditor(): EditorEx {
val editor = super.createEditor()
editor.setVerticalScrollbarVisible(true)
editor.setHorizontalScrollbarVisible(true)
val settings = editor.settings
settings.isLineNumbersShown = true
settings.isAutoCodeFoldingEnabled = true
settings.isFoldingOutlineShown = true
settings.isAllowSingleLogicalLineFolding = true
settings.isRightMarginShown=true
return editor
}
}
This is what you need to do. The key here is to use LanguageTextField instead of EditorTextField and override the createEditor() method to configure all the options that you are looking for like Line Numbers and Code Folding.

Related

Kotlin Annotation processor doesn't add import for generated files

I have an Annotation-processor, which should generate a class MyGeneratedClass containing a variable of another class MyEntity.
My code inside the processfunction:
val elementsWithAnnotation = roundEnv.getElementsAnnotatedWith(MyClass::class.java)
if (elementsWithAnnotation.isEmpty()) {
return true
}
val fileName = "MyGeneratedClass"
val packageName = "me.myname.sdk.generated"
val classBuilder = TypeSpec.classBuilder(fileName)
for (element in elementsWithAnnotation) {
val ann = element.getAnnotation(MyClass::class.java)
println("package: "+ ann.javaClass.packageName)
val variableBuilder =
PropertySpec.varBuilder(
name = element.simpleName.toString(),
type = ClassName("", element.asType().asTypeName().asNullable().toString()),
).initializer("null")
classBuilder
.addProperty(variableBuilder.build())
}
val file = FileSpec.builder(packageName, fileName)
.addType(classBuilder.build())
.build()
val generatedDirectory = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME]
file.writeTo(File(generatedDirectory, "$fileName.kt"))
return true
But the generated code misses the import MyEntity
package me.myname.sdk.generated
class MyGeneratedClass {
var MyEntity: MyEntity? = null
}
When looking inside the generated file, IntelliJ suggests me to import MyEntity, which resolves the error. But how can I achieve, that the import MyEntity statement is being added when generating the file?
looking at the kotlinpoet documentation https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/-class-name/index.html
seems like the first argument in your code, which is a empty string is the package name you are missing in the generated code.
in my experience kotlinpoet is much happier to generate code that in in packages. it sometimes does silly things with types in the root/default package.

Add a PsiElement without adding text to the PsiFile

I'm trying to add a method (PsiMethod) to a class (PsiClass) so that IDEA shows this method when typing. I did this, but I ran into a problem: when I add PsiMethod to PsiClass, the text of this method appears in the file, and I don't need it. I need to add a method so that it is highlighted by IDEA, but it is not displayed in the file as text.
How can this be done?
Here is my code how I add PsiMethod to PsiClass:
val module = ModuleManager.getInstance(project).modules.first()
val file = FilenameIndex
.getFilesByName(
project,
"TestPsiFile.java",
module.moduleContentScope)
.first()
val newMethod = PsiElementFactory.getInstance(project).createMethod("testMethod", PsiType.VOID)
WriteCommandAction.runWriteCommandAction(project) {
file.children
.filter { it.elementType == JavaElementType.CLASS }
.map { it.add(newMethod) }
}
Link to this question in the Jetbrains Community: link

Parsing pdf with Kotlin using a Uri?

I write Kotlin code in Android Studio. The user chooses a file from the phone (I need to access the content as a string). There I get a Uri?. With that Uri? I can extract text from .csv and .txt files:
if (typeOfFile == ".txt" || typeOfFile == ".csv") {
try {
val ins: InputStream? = contentResolver?.openInputStream(uriFromSelectedFile)
val reader = BufferedReader(ins!!.reader())
textIWant = reader.readText()
...
Getting the file type also works fine, but when it comes to opening pdf files, nothing seems to work. I tried using PDFBox from Apache in various ways. The pdf I try to open is a simple onePager and contains only extractable text (can be copied) like this pdf.
This is one of the things I tried, the phone freezes when the file to open is a pdf:
if (typeOfFile == ".pdf") {
try {
val myPDDocument:PDDocument = PDDocument(COSDocument(ScratchFile(File(uriFromSelectedFile.path))))
textIWant = PDFTextStripper().getText(myPDDocument)
...
I´ve been trying for days. Does anyone know, how it works in Kotlin?
It worked using tom_roush.pdfbox and a companion object:
import com.tom_roush.pdfbox.text.PDFTextStripper
class MainActivity : AppCompatActivity() {
companion object PdfParser {
fun parse(fis: InputStream): String {
var content = ""
com.tom_roush.pdfbox.pdmodel.PDDocument.load(fis).use { pdfDocument ->
if (!pdfDocument.isEncrypted) {
content = PDFTextStripper().getText(pdfDocument)
}
}
return content
}
}
Calling the parse function of the companion object:
val fis: InputStream = contentResolver?.openInputStream(uriFromSelectedFile)!!
textIWant = parse(fis)

Configure array/object indentation for YAML in Jackson

I'm trying to generate a YAML file from an input Map I'm using Jackson and the YamlFactory utility provided by Jackson to do so. I'm attempting to configure the indentation property for the YAML output, but it doesn't seem like that's being respected at all.
Here's how my code looks like:
fun getSdkResultAsGenericObject(sdkResult: Any?): Any? {
if (sdkResult == null) {
return null
}
var genericObj: Any?
val stringified = genericSdkObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(sdkResult)
.replace("\n", "")
val isArray = stringified.startsWith("[")
genericObj = if (isArray) {
genericSdkObjectMapper.readValue(stringified, List::class.java)
} else {
genericSdkObjectMapper.readValue(stringified, LinkedHashMap::class.java)
}
val defaultYaml = resultYamlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(genericObj )
}
The declaration of the resultYamlMapper is like this:
val yamlFactory = YAMLFactory()
.configure(YAMLGenerator.Feature.SPLIT_LINES, false)
.configure(YAMLGenerator.Feature.INDENT_ARRAYS, true)
val resultYamlMapper = ObjectMapper(YamlFactory())
The documentation says that the INDENT_ARRAYS feature uses 2 spaces by default. I'm trying to understand how I can configure that? I need 4 spaces in the resultant YAML. I tried setting a pretty print writer:
val yamlFactory = YAMLFactory()
.configure(YAMLGenerator.Feature.SPLIT_LINES, false)
.configure(YAMLGenerator.Feature.INDENT_ARRAYS, true)
val resultYamlMapper = ObjectMapper(YamlFactory())
val arrayIndenter = DefaultIndenter(" ", DefaultIndenter.SYS_LF)
val objectIndenter = DefaultIndenter(" ", DefaultIndenter.SYS_LF)
resultYamlMapper.setDefaultPrettyPrinter(DefaultPrettyPrinter().withObjectIndenter(objectIndenter).withArrayIndenter(arrayIndenter))
But this doesn't seem to be respected at all. Any thoughts? Or does Jackson not let you configure the indentation at all?
The docs show that the PrettyPrinter interface is only for the JsonGenerator.
If you want to customize your YAML output, you have to use the SnakeYAML API directly (which is used by Jackson for YAML processing). SnakeYAML has similar features to Jackson and there is little reason to use Jackson if you only want to process YAML. Most importantly, it lets you configure YAML formatting.

What is a replacement for meta runners in TeamCity Kotlin DSL?

Apparently there's no support for metarunners generation in TeamCity Kotlin DSL. The files remain in plain XML.
How do I replace it using available DSL features? Say I'd like to do this:
steps {
step {
type = "mymetarunner" // compound meta-runner step
}
}
How do I define mymetarunner using Kotlin?
At the moment (TeamCity 2017.2), there is no way to define metarunners using Kotlin DSL.
Update
If having a real metarunner is not required, the solution is a small exercise in Kotlin DSL
Define a container class for settings you need for "metarunner"
class MyConfigClass {
var name = "Default Name"
var goals = "build"
var tasks = "build test"
var someUnusedProperty = 0
}
Define an extension function for steps block
fun BuildSteps.myMetaRunner(config: MyConfigClass.() -> Unit) {
val actualConfig = MyConfigClass() // new config instance
actualConfig.config() // apply closure to fill the config
// use the config to create actual steps
maven {
name = actualConfig.name
goals = actualConfig.goals
}
ant {
name = actualConfig.tasks
}
}
Use the extension function wherever you need
object A_Build : BuildType({
uuid = ...
steps {
myMetaRunner {
name = "This name will be used by maven step"
goals = "build whatever_goal"
tasks = "more ant tasks"
}
}
})
Bingo!