Skip to content

Commit

Permalink
Merge branch 'master' into feature/gradle-tests#653
Browse files Browse the repository at this point in the history
  • Loading branch information
petertrr authored Dec 22, 2020
2 parents 97ddc57 + 5651364 commit ff191c7
Show file tree
Hide file tree
Showing 9 changed files with 647 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import org.cqfn.diktat.ruleset.utils.isPascalCase
import org.cqfn.diktat.ruleset.utils.isTextLengthInRange
import org.cqfn.diktat.ruleset.utils.isUpperSnakeCase
import org.cqfn.diktat.ruleset.utils.removePrefix
import org.cqfn.diktat.ruleset.utils.search.findAllVariablesWithUsages
import org.cqfn.diktat.ruleset.utils.toLowerCamelCase
import org.cqfn.diktat.ruleset.utils.toPascalCase
import org.cqfn.diktat.ruleset.utils.toUpperSnakeCase
Expand All @@ -47,16 +48,21 @@ import com.pinterest.ktlint.core.ast.ElementType.CATCH
import com.pinterest.ktlint.core.ast.ElementType.CATCH_KEYWORD
import com.pinterest.ktlint.core.ast.ElementType.DESTRUCTURING_DECLARATION
import com.pinterest.ktlint.core.ast.ElementType.DESTRUCTURING_DECLARATION_ENTRY
import com.pinterest.ktlint.core.ast.ElementType.FILE
import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_TYPE
import com.pinterest.ktlint.core.ast.ElementType.PROPERTY
import com.pinterest.ktlint.core.ast.ElementType.REFERENCE_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.TYPE_PARAMETER
import com.pinterest.ktlint.core.ast.ElementType.TYPE_REFERENCE
import com.pinterest.ktlint.core.ast.ElementType.VALUE_PARAMETER_LIST
import com.pinterest.ktlint.core.ast.parent
import com.pinterest.ktlint.core.ast.prevCodeSibling
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
import org.jetbrains.kotlin.psi.psiUtil.parents

/**
Expand Down Expand Up @@ -134,10 +140,13 @@ class IdentifierNaming(private val configRules: List<RulesConfig>) : Rule("ident
/**
* all checks for case and naming for vals/vars/constants
*/
@Suppress("SAY_NO_TO_VAR")
@Suppress("SAY_NO_TO_VAR", "TOO_LONG_FUNCTION", "ComplexMethod")
private fun checkVariableName(node: ASTNode): List<ASTNode> {
// special case for Destructuring declarations that can be treated as parameters in lambda:
var namesOfVariables = extractVariableIdentifiers(node)
// Only local private properties will be autofix in order not to break code if there are usages in other files.
// Destructuring declarations are only allowed for local variables/values, so we don't need to calculate `isFix` for every node in `namesOfVariables`
val isFix = isFixMode && if (node.elementType == PROPERTY) (node.psi as KtProperty).run { isLocal || isPrivate() } else true
namesOfVariables
.forEach { variableName ->
// variable should not contain only one letter in it's name. This is a bad example: b512
Expand All @@ -154,15 +163,21 @@ class IdentifierNaming(private val configRules: List<RulesConfig>) : Rule("ident
// it should be in UPPER_CASE, no need to raise this warning if it is one-letter variable
if (node.isConstant()) {
if (!variableName.text.isUpperSnakeCase() && variableName.text.length > 1) {
CONSTANT_UPPERCASE.warnAndFix(configRules, emitWarn, isFixMode, variableName.text, variableName.startOffset, node) {
CONSTANT_UPPERCASE.warnAndFix(configRules, emitWarn, isFix, variableName.text, variableName.startOffset, node) {
(variableName as LeafPsiElement).replaceWithText(variableName.text.toUpperSnakeCase())
}
}
} else if (variableName.text != "_" && !variableName.text.isLowerCamelCase()) {
// variable name should be in camel case. The only exception is a list of industry standard variables like i, j, k.
VARIABLE_NAME_INCORRECT_FORMAT.warnAndFix(configRules, emitWarn, isFixMode, variableName.text, variableName.startOffset, node) {
VARIABLE_NAME_INCORRECT_FORMAT.warnAndFix(configRules, emitWarn, isFix, variableName.text, variableName.startOffset, node) {
// FixMe: cover fixes with tests
(variableName as LeafPsiElement).replaceWithText(variableName.text.toLowerCamelCase())
val correctVariableName = variableName.text.toLowerCamelCase()
variableName
.parent({it.elementType == FILE})
?.findAllVariablesWithUsages { it.name == variableName.text }
?.flatMap { it.value.toList() }
?.forEach { (it.node.firstChildNode as LeafPsiElement).replaceWithText(correctVariableName)}
(variableName as LeafPsiElement).replaceWithText(correctVariableName)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,39 @@ private val loWerValue = ""
private val lower = ""
private val valNX256 = ""
private val voiceIpPort = ""

class A {
private val voiceIpPort = ""
public val valN_x2567 = ""

fun foo() {
val voiceIpPorts = ""
val upperSnakers = voiceIpPort
qww(voiceIpPorts)
}

fun goo() {
val qwe = lowerSnake
val pre = valNX256
}
}

class B {
companion object {
val QQ = 1
private val qwe = 11
}

fun foo() {
var qq = 20
while (qq < 20) {
qq = 10
}
}

class Ba {
fun goo() {
val qwe = QQ
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,39 @@ private val loWer_VAlue = ""
private val lower = ""
private val ValN_x256 = ""
private val VoiceIP_port = ""

class A {
private val VoiceIP_port = ""
public val valN_x2567 = ""

fun foo() {
val VoiceIP_ports = ""
val UPPER_SNAKERS = VoiceIP_port
qww(VoiceIP_ports)
}

fun goo() {
val qwe = lower_snake
val pre = ValN_x256
}
}

class B {
companion object {
val QQ = 1
private val QWE = 11
}

fun foo() {
var QQ = 20
while (QQ < 20) {
QQ = 10
}
}

class BA {
fun goo() {
val qwe = QQ
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fun generateFullDoc(guideDir: File, fullDocFileName: String) {
.flatten()
.joinToString("\n")

val tableOfContent = File(guideDir, "table-of-content.md")
val tableOfContent = File(guideDir, "guide-TOC.md")
.readText()

File(guideDir, fullDocFileName).writeText("$tableOfContent\n\n$allChapters")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ fun generateAvailableRules(rootDir: File, wpDir: File) {
.map { it[2].replace("\\s+".toRegex(), "") to it[5] }
.forEach { ruleMap[it.first]!!.config = it.second}
val newText = File(wpDir, "sections/appendix.tex").readLines().toMutableList()
newText.removeAll(newText.subList(newText.indexOf("\\section*{available-rules}") + 1, newText.indexOf("\\section*{\\textbf{Diktat Coding Convention}}")))
var index = newText.indexOf("\\section*{available-rules}") + 1
newText.removeAll(newText.subList(newText.indexOf("\\section*{Available Rules}") + 1, newText.indexOf("\\lstMakeShortInline[basicstyle=\\ttfamily\\bfseries]`")))
var index = newText.indexOf("\\section*{Available Rules}") + 1
AUTO_TABLE.trimIndent().lines().forEach { newText.add(index++, it) }
ruleMap.map { it.value }
.map { "${it.correctRuleName} & ${it.correctCodeStyle} & ${it.autoFix} & ${it.config.replace("<br>", " ")}\\\\" }
.forEach { newText.add(index++, it) }
AUTO_END.trimIndent().split("\n").forEach { newText.add(index++, it) }

File(wpDir, "sections/appendix.tex").writeText(newText.joinToString(separator = "\n"))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package org.cqfn.diktat.generation.docs

import java.io.File
import java.io.PrintWriter

/**
* Adds/updates diktat code style in white paper document.
Expand All @@ -18,10 +19,31 @@ import java.io.File
fun generateCodeStyle(guideDir: File, wpDir: File) {
val file = File(guideDir, "diktat-coding-convention.md")
val tempFile = File(wpDir, "convention.tex")
val lines = file.readLines().toMutableList()
val lines = file.readLines().toMutableList().drop(1)
tempFile.printWriter().use { writer ->
val iterator = lines.iterator()
writer.writeln("\\lstMakeShortInline[basicstyle=\\ttfamily\\bfseries]`")
while (iterator.hasNext()) {
val line = iterator.next()
if (line.contains("## <a name=\"c0\"></a> Preface"))
break;

when {
line.startsWith("#") -> {
writer.writeln("\\section*{${line.removePrefix("#").trim()}}")
}
line.startsWith("*") -> {
writeTableContentLine(writer, line, 0.5)
}
line.startsWith(" ") -> {
writeTableContentLine(writer, line, 1.0)
}
else -> {
writeTableContentLine(writer, line, 0.0)
}
}
}

while (iterator.hasNext()) {
var line = iterator.next()
if (line.contains("<!--")) {
Expand All @@ -42,6 +64,7 @@ fun generateCodeStyle(guideDir: File, wpDir: File) {
if (name.isNullOrEmpty() || number.isNullOrEmpty()) {
if (number.isNullOrEmpty() && name.isNullOrEmpty()) {
when (line.takeWhile { it == '#' }.count()) {
1 -> writer.writeln("""\section*{\textbf{${line.removePrefix("#").trim()}}}""")
2 -> writer.writeln("""\section*{\textbf{${line.removePrefix("##").trim()}}}""")
3 -> writer.writeln("""\subsection*{\textbf{${line.removePrefix("###").trim()}}}""")
4 -> writer.writeln("""\subsubsection*{\textbf{${line.removePrefix("####").trim()}}}${"\n"}\leavevmode\newline""")
Expand Down Expand Up @@ -109,18 +132,36 @@ fun generateCodeStyle(guideDir: File, wpDir: File) {
correctedString = correctedString.replace("&", "\\&")
correctedString = correctedString.replace("_", "\\_")
// find backticks should be the last to replace \_ with _
correctedString = handleHyperlinks(correctedString)
correctedString = findBoldOrItalicText(BACKTICKS_TEXT, correctedString, FindType.BACKTICKS)

writer.writeln(correctedString)
}
}
}
val appendixFileLines = File(wpDir, "sections/appendix.tex").readLines().toMutableList()
appendixFileLines.removeAll(appendixFileLines.subList(appendixFileLines.indexOf("\\section*{guide}"), appendixFileLines.lastIndex + 1))
val appendixFileLines = File(wpDir, "sections/appendix.tex")
.readLines()
.takeWhile { it != "\\lstMakeShortInline[basicstyle=\\ttfamily\\bfseries]`" }
.toMutableList()
appendixFileLines.addAll(tempFile.readLines())
File(wpDir, "sections/appendix.tex").writeText(appendixFileLines.joinToString(separator = "\n"))
tempFile.delete()
}

private fun writeTableContentLine(writer: PrintWriter, line: String, numbOfSpaces: Double) {
writer.write("\\hspace{${numbOfSpaces}cm}")
writer.writeln(line
.trim()
.replace("[", "")
.replace("]", "")
.replace("*", "")
.replace(ANCHORS, "")
.replace("_", "\\_")
.replace("#", "\\#")
.replace("&", "\\&")
)
}

/**
* Type of text in markdown to be written in latex
*/
Expand All @@ -131,6 +172,28 @@ enum class FindType {
;
}

private fun handleHyperlinks(line: String): String {
var correctedString = line
if (correctedString.contains(HYPERLINKS)) {
val hyperlinkSubString = HYPERLINKS.findAll(correctedString)
hyperlinkSubString.forEach {
var (text, link) = HYPERLINKS.find(it.value)!!.destructured
// need to replace back, because it is a hyperlink
link = link.trim().drop(1).dropLast(1) // drop ( and )
link = link.replace("\\#", "#")
link = link.replace("\\&", "&")
link = link.replace("\\_", "_")
// need to replace ` in hyperlink, because it breaks latex compilation
text = text.replace("`", "")
text = text.trim().drop(1).dropLast(1) // dropping [ and ]
val hyperlink = """\href{$link}{$text}"""
correctedString = correctedString.replace(it.value, hyperlink)
}
}

return correctedString
}

@Suppress("WRONG_INDENTATION")
private fun findBoldOrItalicText(regex: Regex,
line: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ val BOLD_TEXT = Regex("""\*\*([^*]+)\*\*""") // finds bold text in regular line
@Suppress("VARIABLE_NAME_INCORRECT_FORMAT")
val ITALIC_TEXT = Regex("""\*([A-Za-z ]+)\*""") // finds italic text in regular lines
@Suppress("VARIABLE_NAME_INCORRECT_FORMAT")
val HYPERLINKS = Regex("""(\[[a-zA-Z 0-9-_`]*])(\(http[a-z/.#:A-Z-0-9\\_]*\))""") // used to find hyperlinks in line
@Suppress("VARIABLE_NAME_INCORRECT_FORMAT")
val BACKTICKS_TEXT = Regex("""`([^`]*)`""") // finds backtick in regular text (not used for now, may be we will need to use it in future)
@Suppress("VARIABLE_NAME_INCORRECT_FORMAT")
val ANCHORS = Regex("""\(#([a-zA-Z0-9-.]*)\)""") // finds anchors on rules and deletes them
@Suppress("VARIABLE_NAME_INCORRECT_FORMAT")
val TABLE_COLUMN_NAMES = Regex("""[A-Za-z ]*""") // used to find column names in tables only

const val REGEX_PLACEHOLDER = "RE_PL_AC_E_ME"
@Suppress("CONSTANT_UPPERCASE")
const val A4_PAPER_WIDTH = 15f
Expand Down
Loading

0 comments on commit ff191c7

Please sign in to comment.