├── .circleci
└── config.yml
├── .editorconfig
├── .gitignore
├── LICENSE.txt
├── README.md
├── build.gradle.kts
├── buildScripts
└── detekt
│ └── detekt.yml
├── common
├── build.gradle.kts
└── src
│ └── main
│ ├── kotlin
│ └── org
│ │ └── jetbrains
│ │ └── research
│ │ └── deepbugs
│ │ └── common
│ │ ├── CommonResourceBundle.kt
│ │ ├── DeepBugsConfig.kt
│ │ ├── DeepBugsConfigHandler.kt
│ │ ├── DeepBugsPlugin.kt
│ │ ├── datatypes
│ │ ├── BinOp.kt
│ │ ├── Call.kt
│ │ └── DataType.kt
│ │ ├── ide
│ │ ├── error
│ │ │ └── DeepBugsErrorReporter.kt
│ │ ├── fus
│ │ │ ├── DeepBugsEventLogger.kt
│ │ │ ├── DeepBugsEventLoggerProvider.kt
│ │ │ └── collectors
│ │ │ │ └── counter
│ │ │ │ └── DeepBugsCounterCollector.kt
│ │ ├── inspections
│ │ │ ├── DeepBugsInspectionManager.kt
│ │ │ └── specific
│ │ │ │ └── SpecificInspectionDescriptor.kt
│ │ ├── msg
│ │ │ ├── DeepBugsLifecycle.kt
│ │ │ └── InspectionStateHandler.kt
│ │ ├── problem
│ │ │ └── BugDescriptor.kt
│ │ ├── quickfixes
│ │ │ ├── FlipFunctionArgumentsQuickFix.kt
│ │ │ └── ReplaceBinOperatorQuickFix.kt
│ │ └── ui
│ │ │ ├── DeepBugsConfigurable.kt
│ │ │ ├── DeepBugsSettingsPanel.kt
│ │ │ └── UiUtils.kt
│ │ ├── model
│ │ ├── CommonModelStorage.kt
│ │ ├── ModelHandler.kt
│ │ ├── Vocabulary.kt
│ │ └── common
│ │ │ └── CommonModel.kt
│ │ └── utils
│ │ ├── Cbor.kt
│ │ └── Mapping.kt
│ └── resources
│ └── DeepBugsCommonBundle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── js-plugin
├── build.gradle.kts
└── src
│ ├── main
│ ├── kotlin
│ │ └── org
│ │ │ └── jetbrains
│ │ │ └── research
│ │ │ └── deepbugs
│ │ │ └── javascript
│ │ │ ├── JSDeepBugsConfig.kt
│ │ │ ├── JSResourceBundle.kt
│ │ │ ├── datatypes
│ │ │ └── JSDataTypeUtils.kt
│ │ │ ├── extraction
│ │ │ └── JSExtraction.kt
│ │ │ ├── ide
│ │ │ ├── inspections
│ │ │ │ ├── base
│ │ │ │ │ ├── JSDeepBugsBaseInspection.kt
│ │ │ │ │ ├── JSDeepBugsBinExprInspection.kt
│ │ │ │ │ └── JSDeepBugsCallExprInspection.kt
│ │ │ │ ├── common
│ │ │ │ │ ├── JSDeepBugsBinOperandInspection.kt
│ │ │ │ │ ├── JSDeepBugsBinOperatorInspection.kt
│ │ │ │ │ └── JSDeepBugsSwappedArgsInspection.kt
│ │ │ │ └── specific
│ │ │ │ │ └── math
│ │ │ │ │ ├── JSDeepBugsIncorrectArgMathInspection.kt
│ │ │ │ │ ├── JSDeepBugsMathCallExprInspection.kt
│ │ │ │ │ └── JSDeepBugsSwappedArgsMathInspection.kt
│ │ │ ├── quickfixes
│ │ │ │ ├── JSFlipFunctionArgumentsQuickFix.kt
│ │ │ │ ├── JSIgnoreExpressionQuickFix.kt
│ │ │ │ └── utils
│ │ │ │ │ └── JSOperatorMap.kt
│ │ │ └── ui
│ │ │ │ └── JSDeepBugsConfigurable.kt
│ │ │ └── model
│ │ │ └── specific
│ │ │ ├── JSSpecificModel.kt
│ │ │ └── MathModel.kt
│ ├── models
│ │ ├── common
│ │ │ ├── binOperandDetectionModel.h5
│ │ │ ├── binOperatorDetectionModel.h5
│ │ │ └── swappedArgsDetectionModel.h5
│ │ ├── math
│ │ │ ├── incorrectFuncArgDetectionModelMath.h5
│ │ │ └── swappedArgsDetectionModelMath.h5
│ │ ├── nodeTypeToVector.cbor
│ │ ├── operatorToVector.cbor
│ │ ├── tokenToVector.cbor
│ │ └── typeToVector.cbor
│ └── resources
│ │ ├── DeepBugsJavaScriptBundle.properties
│ │ ├── META-INF
│ │ ├── plugin.xml
│ │ └── pluginIcon.svg
│ │ └── inspectionDescriptions
│ │ ├── JSDeepBugsBinOperand.html
│ │ ├── JSDeepBugsBinOperator.html
│ │ ├── JSDeepBugsIncorrectArgMath.html
│ │ ├── JSDeepBugsSwappedArgs.html
│ │ └── JSDeepBugsSwappedArgsMath.html
│ └── test
│ ├── kotlin
│ └── org
│ │ └── jetbrains
│ │ └── research
│ │ └── deepbugs
│ │ └── javascript
│ │ ├── DeepBugsTestBase.kt
│ │ └── JSDeepBugsTest.kt
│ └── testData
│ ├── testIncorrectArgumentMathJS.js
│ ├── testIncorrectBinOperandJS.js
│ ├── testIncorrectBinOperatorJS.js
│ ├── testSwappedArgumentsJS.js
│ └── testSwappedArgumentsMathJS.js
├── keras-runner
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ └── org
│ └── jetbrains
│ └── research
│ └── keras
│ └── runner
│ ├── deserializer
│ ├── ModelLoader.kt
│ ├── Utils.kt
│ └── json
│ │ ├── ActivationType.kt
│ │ ├── LayerConfig.kt
│ │ ├── LayerScheme.kt
│ │ ├── ModelConfig.kt
│ │ └── ModelScheme.kt
│ └── nn
│ ├── activation
│ ├── ActivatableVector.kt
│ └── ActivationFunction.kt
│ ├── layer
│ ├── ActivatableLayer.kt
│ ├── Layer.kt
│ └── dense
│ │ ├── DenseLayer.kt
│ │ └── DenseParameters.kt
│ └── model
│ ├── Model.kt
│ └── sequential
│ ├── Perceptron.kt
│ └── SequentialModel.kt
├── py-plugin
├── build.gradle.kts
└── src
│ ├── main
│ ├── kotlin
│ │ └── org
│ │ │ └── jetbrains
│ │ │ └── research
│ │ │ └── deepbugs
│ │ │ └── python
│ │ │ ├── PyDeepBugsConfig.kt
│ │ │ ├── PyResourceBundle.kt
│ │ │ ├── datatypes
│ │ │ └── PyDataTypeUtils.kt
│ │ │ ├── extraction
│ │ │ └── PyExtraction.kt
│ │ │ └── ide
│ │ │ ├── inspections
│ │ │ ├── PyDeepBugsBinOperandInspection.kt
│ │ │ ├── PyDeepBugsBinOperatorInspection.kt
│ │ │ ├── PyDeepBugsSwappedArgsInspection.kt
│ │ │ └── base
│ │ │ │ ├── PyDeepBugsBaseInspection.kt
│ │ │ │ ├── PyDeepBugsBinExprInspection.kt
│ │ │ │ └── PyDeepBugsCallExprInspection.kt
│ │ │ ├── quickfixes
│ │ │ ├── PyFlipFunctionArgumentsQuickFix.kt
│ │ │ └── PyIgnoreExpressionQuickFix.kt
│ │ │ └── ui
│ │ │ └── PyDeepBugsConfigurable.kt
│ ├── models
│ │ ├── common
│ │ │ ├── binOperandDetectionModel.h5
│ │ │ ├── binOperatorDetectionModel.h5
│ │ │ └── swappedArgsDetectionModel.h5
│ │ ├── nodeTypeToVector.cbor
│ │ ├── operatorToVector.cbor
│ │ ├── tokenToVector.cbor
│ │ └── typeToVector.cbor
│ └── resources
│ │ ├── DeepBugsPythonBundle.properties
│ │ ├── META-INF
│ │ ├── plugin.xml
│ │ └── pluginIcon.svg
│ │ └── inspectionDescriptions
│ │ ├── PyDeepBugsBinOperand.html
│ │ ├── PyDeepBugsBinOperator.html
│ │ └── PyDeepBugsSwappedArgs.html
│ └── test
│ ├── kotlin
│ └── org
│ │ └── jetbrains
│ │ └── research
│ │ └── deepbugs
│ │ └── python
│ │ ├── DeepBugsTestBase.kt
│ │ └── PyDeepBugsTest.kt
│ └── testData
│ ├── testIncorrectBinOperandPy.py
│ ├── testIncorrectBinOperatorPy.py
│ └── testSwappedArgumentsPy.py
└── settings.gradle.kts
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | docker:
5 | - image: circleci/openjdk:8-jdk
6 | working_directory: ~
7 | steps:
8 | - checkout
9 | - run: ./gradlew build
10 |
11 | release:
12 | docker:
13 | - image: circleci/openjdk:8-jdk
14 | working_directory: ~
15 | steps:
16 | - checkout
17 | - run: ./gradlew publishPlugin
18 | workflows:
19 | version: 2
20 | build:
21 | jobs:
22 | - build:
23 | filters:
24 | branches:
25 | ignore:
26 | - /dev-.*/
27 | - /stable-.*/
28 | release:
29 | jobs:
30 | - build:
31 | filters:
32 | branches:
33 | only:
34 | - /dev-.*/
35 | - /stable-.*/
36 | - approve-release:
37 | type: approval
38 | requires:
39 | - build
40 | - release:
41 | requires:
42 | - approve-release
43 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | end_of_line = lf
3 | insert_final_newline = true
4 | max_line_length = 160
5 |
6 | [*.kt]
7 | indent_style = space
8 | indent_size = 4
9 | ij_kotlin_name_count_to_use_star_import = 3
10 | ij_kotlin_name_count_to_use_star_import_for_members = 3
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | out
3 | build
4 | .gradle
5 | *.iml
6 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 JetBrains-Research
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
DeepBugs for IntelliJ
2 |
3 | [](https://research.jetbrains.org/)
4 | [](https://circleci.com/gh/JetBrains-Research/DeepBugsPlugin)
5 | [](https://gitter.im/deepbugs4intellij/community)
6 | [](https://plugins.jetbrains.com/plugin/12220-deepbugsjavascript)
7 | [](https://plugins.jetbrains.com/plugin/12220-deepbugsjavascript)
8 | [](https://plugins.jetbrains.com/plugin/12218-deepbugspython)
9 | [](https://plugins.jetbrains.com/plugin/12218-deepbugspython)
10 |
11 |
12 | __DeepBugs for IntelliJ__ is a pair of plugins for IntelliJ-based IDEs that provide semantics-aware bug detection in Python and JavaScript. The plugins use deep learning models inspired by the [DeepBugs framework](https://github.com/michaelpradel/DeepBugs) to extract the semantics of code and find bugs.
13 |
14 | The plugins are available for download: [Python](https://plugins.jetbrains.com/plugin/12218-deepbugspython/), [JavaScript](https://plugins.jetbrains.com/plugin/12220-deepbugsjavascript/).
15 |
16 |
17 |
18 |
19 |
20 | ## Getting started
21 | Code inspections in the plugins detect several types of bugs, including incorrect function arguments, incorrect comparison, and others, based on code semantics.
22 |
23 | If the plugin provides some warnings that you consider as false positives, you can disable check on any particular piece of code with a quick-fix.
24 | All the ignored expressions can be reset in __Preferences / Settings__ under __Tools | DeepBugs for Python/DeepBugs for JavaScript__.
25 |
26 | ## Supported code inspections
27 | ### Incorrect binary operator
28 | The inspection detects misuse of binary operators (such as `<`, `<=`, `+`, etc.).
29 |
30 | For example, it may detect the following bugs:
31 | - `i <= length` (index is less or equal to length, but should be less)
32 | - `text + binary` (concatenated non-compatible types)
33 |
34 | This inspection provides a quick-fix that allows replacing misused operator with more appropriate one.
35 | ### Incorrect binary operand
36 | The inspection detects misuse of binary operands (arguments of binary operations).
37 |
38 | For example:
39 | - `height - x` (in most cases it should be `height - y`)
40 | - `j < params` (should be `params.length`)
41 |
42 | ### Incorrect function arguments
43 | The inspection detects misuse of function arguments (specifically, their order).
44 |
45 | For example:
46 | - `startPoller(100, function(delay, fn) { … })` (should be fn, delay)
47 | - `2 % i` (unusual order of operands)
48 |
49 | This inspection provides a quick-fix allowing to fix the order of arguments.
50 |
51 | ## Got any more questions?
52 | If you want to know more about the DeepBugs framework that these plugins are based on, please [refer to this paper](http://software-lab.org/publications/oopsla2018_DeepBugs.pdf).
53 |
54 | If you have any questions about the plugins themselves, please don’t hesitate to contact us on [Gitter](https://gitter.im/deepbugs4intellij/community).
55 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import io.gitlab.arturbosch.detekt.Detekt
2 | import org.jetbrains.intellij.tasks.BuildSearchableOptionsTask
3 | import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile
4 | import tanvd.kosogor.defaults.configureIdea
5 |
6 | group = "org.jetbrains.research.deepbugs"
7 | version = "0.5"
8 |
9 | plugins {
10 | id("tanvd.kosogor") version "1.0.7" apply true
11 | id("io.gitlab.arturbosch.detekt") version ("1.6.0") apply false
12 | id("org.jetbrains.intellij") version "0.4.13" apply true
13 | kotlin("jvm") version "1.3.70" apply true
14 | id("org.jetbrains.kotlin.plugin.serialization") version "1.3.70" apply true
15 | }
16 |
17 | intellij {
18 | version = "2020.1"
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | jcenter()
24 | maven("https://dl.bintray.com/mipt-npm/scientifik")
25 | }
26 | }
27 |
28 | subprojects {
29 | apply {
30 | plugin("kotlin")
31 | plugin("org.jetbrains.kotlin.plugin.serialization")
32 | plugin("org.jetbrains.intellij")
33 | plugin("tanvd.kosogor")
34 | plugin("io.gitlab.arturbosch.detekt")
35 | }
36 |
37 | tasks.withType().forEach { it.enabled = false }
38 |
39 | configureIdea {
40 | exclude += file("build")
41 | }
42 |
43 | intellij {
44 | sandboxDirectory = File(rootProject.projectDir, "build/${project.name}/idea-sandbox").canonicalPath
45 | }
46 |
47 | tasks.withType {
48 | parallel = true
49 | failFast = false
50 | config.setFrom(File(rootProject.projectDir, "buildScripts/detekt/detekt.yml"))
51 | reports {
52 | xml.enabled = false
53 | html.enabled = false
54 | }
55 | }
56 |
57 | dependencies {
58 | compileOnly(kotlin("stdlib"))
59 | compileOnly(kotlin("stdlib-jdk8"))
60 | implementation("org.jetbrains.kotlinx", "kotlinx-serialization-cbor", "0.20.0") {
61 | exclude("org.jetbrains.kotlin")
62 | }
63 | }
64 |
65 | tasks.withType {
66 | kotlinOptions {
67 | jvmTarget = "1.8"
68 | languageVersion = "1.3"
69 | apiVersion = "1.3"
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/buildScripts/detekt/detekt.yml:
--------------------------------------------------------------------------------
1 | build:
2 | maxIssues: 10
3 | excludeCorrectable: false
4 | weights:
5 | # complexity: 2
6 | # LongParameterList: 1
7 | # style: 1
8 | # comments: 1
9 |
10 | config:
11 | validation: true
12 | # when writing own rules with new properties, exclude the property path e.g.: "my_rule_set,.*>.*>[my_property]"
13 | excludes: ""
14 |
15 | processors:
16 | active: true
17 | exclude:
18 | - 'DetektProgressListener'
19 | # - 'FunctionCountProcessor'
20 | # - 'PropertyCountProcessor'
21 | # - 'ClassCountProcessor'
22 | # - 'PackageCountProcessor'
23 | # - 'KtFileCountProcessor'
24 |
25 | console-reports:
26 | active: true
27 | exclude:
28 | - 'ProjectStatisticsReport'
29 | - 'ComplexityReport'
30 | - 'NotificationReport'
31 | # - 'FindingsReport'
32 | - 'FileBasedFindingsReport'
33 |
34 | comments:
35 | active: true
36 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
37 | CommentOverPrivateFunction:
38 | active: false
39 | CommentOverPrivateProperty:
40 | active: false
41 | EndOfSentenceFormat:
42 | active: false
43 | endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!:]$)
44 | UndocumentedPublicClass:
45 | active: false
46 | searchInNestedClass: true
47 | searchInInnerClass: true
48 | searchInInnerObject: true
49 | searchInInnerInterface: true
50 | UndocumentedPublicFunction:
51 | active: false
52 | UndocumentedPublicProperty:
53 | active: false
54 |
55 | complexity:
56 | active: true
57 | ComplexCondition:
58 | active: true
59 | threshold: 4
60 | ComplexInterface:
61 | active: false
62 | threshold: 10
63 | includeStaticDeclarations: false
64 | ComplexMethod:
65 | active: true
66 | threshold: 15
67 | ignoreSingleWhenExpression: false
68 | ignoreSimpleWhenEntries: false
69 | ignoreNestingFunctions: false
70 | nestingFunctions: run,let,apply,with,also,use,forEach,isNotNull,ifNull
71 | LabeledExpression:
72 | active: false
73 | ignoredLabels: ""
74 | LargeClass:
75 | active: true
76 | threshold: 600
77 | LongMethod:
78 | active: true
79 | threshold: 60
80 | LongParameterList:
81 | active: true
82 | threshold: 6
83 | ignoreDefaultParameters: false
84 | MethodOverloading:
85 | active: false
86 | threshold: 6
87 | NestedBlockDepth:
88 | active: true
89 | threshold: 4
90 | StringLiteralDuplication:
91 | active: false
92 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
93 | threshold: 3
94 | ignoreAnnotation: true
95 | excludeStringsWithLessThan5Characters: true
96 | ignoreStringsRegex: '$^'
97 | TooManyFunctions:
98 | active: true
99 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
100 | thresholdInFiles: 11
101 | thresholdInClasses: 11
102 | thresholdInInterfaces: 11
103 | thresholdInObjects: 11
104 | thresholdInEnums: 11
105 | ignoreDeprecated: false
106 | ignorePrivate: false
107 | ignoreOverridden: false
108 |
109 | coroutines:
110 | active: true
111 | GlobalCoroutineUsage:
112 | active: false
113 | RedundantSuspendModifier:
114 | active: false
115 |
116 | empty-blocks:
117 | active: true
118 | EmptyCatchBlock:
119 | active: true
120 | allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
121 | EmptyClassBlock:
122 | active: true
123 | EmptyDefaultConstructor:
124 | active: true
125 | EmptyDoWhileBlock:
126 | active: true
127 | EmptyElseBlock:
128 | active: true
129 | EmptyFinallyBlock:
130 | active: true
131 | EmptyForBlock:
132 | active: true
133 | EmptyFunctionBlock:
134 | active: true
135 | ignoreOverridden: false
136 | EmptyIfBlock:
137 | active: true
138 | EmptyInitBlock:
139 | active: true
140 | EmptyKtFile:
141 | active: true
142 | EmptySecondaryConstructor:
143 | active: true
144 | EmptyTryBlock:
145 | active: true
146 | EmptyWhenBlock:
147 | active: true
148 | EmptyWhileBlock:
149 | active: true
150 |
151 | exceptions:
152 | active: true
153 | ExceptionRaisedInUnexpectedLocation:
154 | active: false
155 | methodNames: 'toString,hashCode,equals,finalize'
156 | InstanceOfCheckForException:
157 | active: false
158 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
159 | NotImplementedDeclaration:
160 | active: false
161 | PrintStackTrace:
162 | active: false
163 | RethrowCaughtException:
164 | active: false
165 | ReturnFromFinally:
166 | active: false
167 | ignoreLabeled: false
168 | SwallowedException:
169 | active: false
170 | ignoredExceptionTypes: 'InterruptedException,NumberFormatException,ParseException,MalformedURLException'
171 | allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
172 | ThrowingExceptionFromFinally:
173 | active: false
174 | ThrowingExceptionInMain:
175 | active: false
176 | ThrowingExceptionsWithoutMessageOrCause:
177 | active: false
178 | exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
179 | ThrowingNewInstanceOfSameException:
180 | active: false
181 | TooGenericExceptionCaught:
182 | active: false
183 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
184 | exceptionNames:
185 | - ArrayIndexOutOfBoundsException
186 | - Error
187 | - Exception
188 | - IllegalMonitorStateException
189 | - NullPointerException
190 | - IndexOutOfBoundsException
191 | - RuntimeException
192 | - Throwable
193 | allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
194 | TooGenericExceptionThrown:
195 | active: true
196 | exceptionNames:
197 | - Error
198 | - Exception
199 | - Throwable
200 | - RuntimeException
201 |
202 | formatting:
203 | active: true
204 | android: false
205 | autoCorrect: true
206 | AnnotationOnSeparateLine:
207 | active: false
208 | autoCorrect: true
209 | ChainWrapping:
210 | active: true
211 | autoCorrect: true
212 | CommentSpacing:
213 | active: true
214 | autoCorrect: true
215 | EnumEntryNameCase:
216 | active: false
217 | autoCorrect: true
218 | Filename:
219 | active: true
220 | FinalNewline:
221 | active: true
222 | autoCorrect: true
223 | insertFinalNewLine: true
224 | ImportOrdering:
225 | active: false
226 | autoCorrect: true
227 | Indentation:
228 | active: false
229 | autoCorrect: true
230 | indentSize: 4
231 | continuationIndentSize: 4
232 | MaximumLineLength:
233 | active: true
234 | maxLineLength: 120
235 | ModifierOrdering:
236 | active: true
237 | autoCorrect: true
238 | MultiLineIfElse:
239 | active: true
240 | autoCorrect: true
241 | NoBlankLineBeforeRbrace:
242 | active: true
243 | autoCorrect: true
244 | NoConsecutiveBlankLines:
245 | active: true
246 | autoCorrect: true
247 | NoEmptyClassBody:
248 | active: true
249 | autoCorrect: true
250 | NoEmptyFirstLineInMethodBlock:
251 | active: false
252 | autoCorrect: true
253 | NoLineBreakAfterElse:
254 | active: true
255 | autoCorrect: true
256 | NoLineBreakBeforeAssignment:
257 | active: true
258 | autoCorrect: true
259 | NoMultipleSpaces:
260 | active: true
261 | autoCorrect: true
262 | NoSemicolons:
263 | active: true
264 | autoCorrect: true
265 | NoTrailingSpaces:
266 | active: true
267 | autoCorrect: true
268 | NoUnitReturn:
269 | active: true
270 | autoCorrect: true
271 | NoUnusedImports:
272 | active: true
273 | autoCorrect: true
274 | NoWildcardImports:
275 | active: true
276 | PackageName:
277 | active: true
278 | autoCorrect: true
279 | ParameterListWrapping:
280 | active: true
281 | autoCorrect: true
282 | indentSize: 4
283 | SpacingAroundColon:
284 | active: true
285 | autoCorrect: true
286 | SpacingAroundComma:
287 | active: true
288 | autoCorrect: true
289 | SpacingAroundCurly:
290 | active: true
291 | autoCorrect: true
292 | SpacingAroundDot:
293 | active: true
294 | autoCorrect: true
295 | SpacingAroundKeyword:
296 | active: true
297 | autoCorrect: true
298 | SpacingAroundOperators:
299 | active: true
300 | autoCorrect: true
301 | SpacingAroundParens:
302 | active: true
303 | autoCorrect: true
304 | SpacingAroundRangeOperator:
305 | active: true
306 | autoCorrect: true
307 | StringTemplate:
308 | active: true
309 | autoCorrect: true
310 |
311 | naming:
312 | active: true
313 | ClassNaming:
314 | active: true
315 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
316 | classPattern: '[A-Z$][a-zA-Z0-9$]*'
317 | ConstructorParameterNaming:
318 | active: false
319 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
320 | parameterPattern: '[a-z][A-Za-z0-9]*'
321 | privateParameterPattern: '[a-z][A-Za-z0-9]*'
322 | excludeClassPattern: '$^'
323 | ignoreOverridden: true
324 | EnumNaming:
325 | active: false
326 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
327 | enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
328 | ForbiddenClassName:
329 | active: false
330 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
331 | forbiddenName: ''
332 | FunctionMaxLength:
333 | active: false
334 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
335 | maximumFunctionNameLength: 30
336 | FunctionMinLength:
337 | active: false
338 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
339 | minimumFunctionNameLength: 3
340 | FunctionNaming:
341 | active: true
342 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
343 | functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
344 | excludeClassPattern: '$^'
345 | ignoreOverridden: true
346 | FunctionParameterNaming:
347 | active: true
348 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
349 | parameterPattern: '[a-z][A-Za-z0-9]*'
350 | excludeClassPattern: '$^'
351 | ignoreOverridden: true
352 | InvalidPackageDeclaration:
353 | active: false
354 | rootPackage: ''
355 | MatchingDeclarationName:
356 | active: true
357 | mustBeFirst: true
358 | MemberNameEqualsClassName:
359 | active: false
360 | ignoreOverridden: true
361 | ObjectPropertyNaming:
362 | active: true
363 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
364 | constantPattern: '[A-Za-z][_A-Za-z0-9]*'
365 | propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
366 | privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
367 | PackageNaming:
368 | active: true
369 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
370 | packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$'
371 | TopLevelPropertyNaming:
372 | active: true
373 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
374 | constantPattern: '[A-Z][_A-Z0-9]*'
375 | propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
376 | privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
377 | VariableMaxLength:
378 | active: false
379 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
380 | maximumVariableNameLength: 64
381 | VariableMinLength:
382 | active: false
383 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
384 | minimumVariableNameLength: 1
385 | VariableNaming:
386 | active: false
387 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
388 | variablePattern: '[a-z][A-Za-z0-9]*'
389 | privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
390 | excludeClassPattern: '$^'
391 | ignoreOverridden: true
392 |
393 | performance:
394 | active: true
395 | ArrayPrimitive:
396 | active: true
397 | ForEachOnRange:
398 | active: true
399 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
400 | SpreadOperator:
401 | active: false
402 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
403 | UnnecessaryTemporaryInstantiation:
404 | active: true
405 |
406 | potential-bugs:
407 | active: true
408 | Deprecation:
409 | active: false
410 | DuplicateCaseInWhenExpression:
411 | active: true
412 | EqualsAlwaysReturnsTrueOrFalse:
413 | active: true
414 | EqualsWithHashCodeExist:
415 | active: true
416 | ExplicitGarbageCollectionCall:
417 | active: true
418 | HasPlatformType:
419 | active: false
420 | ImplicitDefaultLocale:
421 | active: false
422 | InvalidRange:
423 | active: true
424 | IteratorHasNextCallsNextMethod:
425 | active: true
426 | IteratorNotThrowingNoSuchElementException:
427 | active: true
428 | LateinitUsage:
429 | active: false
430 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
431 | excludeAnnotatedProperties: ""
432 | ignoreOnClassesPattern: ""
433 | MapGetWithNotNullAssertionOperator:
434 | active: false
435 | MissingWhenCase:
436 | active: true
437 | RedundantElseInWhen:
438 | active: true
439 | UnconditionalJumpStatementInLoop:
440 | active: false
441 | UnreachableCode:
442 | active: true
443 | UnsafeCallOnNullableType:
444 | active: true
445 | UnsafeCast:
446 | active: false
447 | UselessPostfixExpression:
448 | active: false
449 | WrongEqualsTypeParameter:
450 | active: true
451 |
452 | style:
453 | active: true
454 | CollapsibleIfStatements:
455 | active: false
456 | DataClassContainsFunctions:
457 | active: false
458 | conversionFunctionPrefix: 'to'
459 | DataClassShouldBeImmutable:
460 | active: false
461 | EqualsNullCall:
462 | active: true
463 | EqualsOnSignatureLine:
464 | active: false
465 | ExplicitCollectionElementAccessMethod:
466 | active: false
467 | ExplicitItLambdaParameter:
468 | active: false
469 | ExpressionBodySyntax:
470 | active: false
471 | includeLineWrapping: false
472 | ForbiddenComment:
473 | active: true
474 | values: 'TODO:,FIXME:,STOPSHIP:'
475 | allowedPatterns: ""
476 | ForbiddenImport:
477 | active: false
478 | imports: ''
479 | forbiddenPatterns: ""
480 | ForbiddenMethodCall:
481 | active: false
482 | methods: ''
483 | ForbiddenPublicDataClass:
484 | active: false
485 | ignorePackages: '*.internal,*.internal.*'
486 | ForbiddenVoid:
487 | active: false
488 | ignoreOverridden: false
489 | ignoreUsageInGenerics: false
490 | FunctionOnlyReturningConstant:
491 | active: true
492 | ignoreOverridableFunction: true
493 | excludedFunctions: 'describeContents'
494 | excludeAnnotatedFunction: "dagger.Provides"
495 | LibraryCodeMustSpecifyReturnType:
496 | active: true
497 | LoopWithTooManyJumpStatements:
498 | active: true
499 | maxJumpCount: 1
500 | MagicNumber:
501 | active: false
502 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
503 | ignoreNumbers: '-1,0,1,2'
504 | ignoreHashCodeFunction: true
505 | ignorePropertyDeclaration: false
506 | ignoreLocalVariableDeclaration: false
507 | ignoreConstantDeclaration: true
508 | ignoreCompanionObjectPropertyDeclaration: true
509 | ignoreAnnotation: false
510 | ignoreNamedArgument: true
511 | ignoreEnums: false
512 | ignoreRanges: false
513 | MandatoryBracesIfStatements:
514 | active: false
515 | MaxLineLength:
516 | active: false
517 | maxLineLength: 120
518 | excludePackageStatements: true
519 | excludeImportStatements: true
520 | excludeCommentStatements: false
521 | MayBeConst:
522 | active: true
523 | ModifierOrder:
524 | active: true
525 | NestedClassesVisibility:
526 | active: false
527 | NewLineAtEndOfFile:
528 | active: true
529 | NoTabs:
530 | active: false
531 | OptionalAbstractKeyword:
532 | active: true
533 | OptionalUnit:
534 | active: false
535 | OptionalWhenBraces:
536 | active: false
537 | PreferToOverPairSyntax:
538 | active: false
539 | ProtectedMemberInFinalClass:
540 | active: true
541 | RedundantExplicitType:
542 | active: false
543 | RedundantVisibilityModifierRule:
544 | active: false
545 | ReturnCount:
546 | active: false
547 | max: 2
548 | excludedFunctions: "equals"
549 | excludeLabeled: false
550 | excludeReturnFromLambda: true
551 | excludeGuardClauses: false
552 | SafeCast:
553 | active: true
554 | SerialVersionUIDInSerializableClass:
555 | active: false
556 | SpacingBetweenPackageAndImports:
557 | active: false
558 | ThrowsCount:
559 | active: true
560 | max: 2
561 | TrailingWhitespace:
562 | active: false
563 | UnderscoresInNumericLiterals:
564 | active: false
565 | acceptableDecimalLength: 5
566 | UnnecessaryAbstractClass:
567 | active: false
568 | excludeAnnotatedClasses: "dagger.Module"
569 | UnnecessaryAnnotationUseSiteTarget:
570 | active: false
571 | UnnecessaryApply:
572 | active: false
573 | UnnecessaryInheritance:
574 | active: true
575 | UnnecessaryLet:
576 | active: false
577 | UnnecessaryParentheses:
578 | active: false
579 | UntilInsteadOfRangeTo:
580 | active: false
581 | UnusedImports:
582 | active: false
583 | UnusedPrivateClass:
584 | active: true
585 | UnusedPrivateMember:
586 | active: false
587 | allowedNames: "(_|ignored|expected|serialVersionUID)"
588 | UseArrayLiteralsInAnnotations:
589 | active: false
590 | UseCheckOrError:
591 | active: false
592 | UseDataClass:
593 | active: false
594 | excludeAnnotatedClasses: ""
595 | allowVars: false
596 | UseIfInsteadOfWhen:
597 | active: false
598 | UseRequire:
599 | active: false
600 | UselessCallOnNotNull:
601 | active: true
602 | UtilityClassWithPublicConstructor:
603 | active: true
604 | VarCouldBeVal:
605 | active: false
606 | WildcardImport:
607 | active: false
608 | excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
609 | excludeImports: 'java.util.*,kotlinx.android.synthetic.*'
610 |
--------------------------------------------------------------------------------
/common/build.gradle.kts:
--------------------------------------------------------------------------------
1 | group = rootProject.group
2 | version = rootProject.version
3 |
4 | intellij {
5 | version = rootProject.intellij.version
6 | }
7 |
8 | dependencies {
9 | implementation(project(":keras-runner"))
10 | }
11 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/CommonResourceBundle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common
2 |
3 | import com.intellij.AbstractBundle
4 | import org.jetbrains.annotations.PropertyKey
5 | import java.util.*
6 |
7 | object CommonResourceBundle {
8 | private const val BUNDLE_NAME = "DeepBugsCommonBundle"
9 |
10 | private val bundle by lazy { ResourceBundle.getBundle(BUNDLE_NAME) }
11 |
12 | fun message(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg params: Any): String {
13 | return AbstractBundle.message(bundle!!, key, *params)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/DeepBugsConfig.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common
2 |
3 | import com.intellij.openapi.components.PersistentStateComponent
4 | import com.intellij.util.xmlb.annotations.Property
5 | import org.jetbrains.research.deepbugs.common.ide.msg.DeepBugsLifecycle
6 |
7 | abstract class DeepBugsConfig(private val default: State) : PersistentStateComponent {
8 | data class State(
9 | @Property val quickFixesThreshold: Float = 0.3f,
10 | @Property val userDisabledChecks: Set = emptySet()
11 | )
12 |
13 | private var myState: State? = null
14 |
15 | override fun getState(): State {
16 | if (myState == null) {
17 | update(default)
18 | }
19 | return myState!!
20 | }
21 |
22 | override fun loadState(state: State) {
23 | update(state)
24 | }
25 |
26 | fun disableCheck(expr: String) {
27 | val newState = State(
28 | userDisabledChecks = state.userDisabledChecks + expr
29 | )
30 | update(newState)
31 | }
32 |
33 | fun enableCheck(expr: String) {
34 | val newState = State(
35 | userDisabledChecks = state.userDisabledChecks - expr
36 | )
37 | update(newState)
38 | }
39 |
40 |
41 | fun update(new: State) {
42 | if (myState == null) {
43 | myState = new
44 |
45 | DeepBugsLifecycle.publisher.init(state)
46 | } else {
47 | val prevState = myState!!
48 | myState = new
49 |
50 | DeepBugsLifecycle.publisher.update(prevState, state)
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/DeepBugsConfigHandler.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common
2 |
3 | import org.jetbrains.research.deepbugs.common.datatypes.DataType
4 |
5 | abstract class DeepBugsConfigHandler {
6 | protected abstract val instance: DeepBugsConfig
7 | abstract val default: DeepBugsConfig.State
8 |
9 | fun get() = instance.state
10 |
11 | @Synchronized
12 | fun ignoreExpression(expr: DataType) = instance.disableCheck(expr.text)
13 |
14 | @Synchronized
15 | fun considerExpression(expr: DataType) = instance.enableCheck(expr.text)
16 |
17 | fun shouldIgnore(expr: DataType) = get().userDisabledChecks.contains(expr.text)
18 |
19 | fun isProblem(result: Float, threshold: Float, expr: DataType) = result > threshold && !shouldIgnore(expr)
20 | }
21 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/DeepBugsPlugin.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common
2 |
3 | import com.intellij.ide.plugins.*
4 | import com.intellij.internal.statistic.utils.*
5 | import com.intellij.openapi.application.ApplicationManager
6 | import org.jetbrains.annotations.TestOnly
7 | import java.io.File
8 |
9 | object DeepBugsPlugin {
10 | private val classLoader: ClassLoader
11 | get() = this::class.java.classLoader
12 |
13 | private var myTestPluginId: String? = null
14 |
15 | private val descriptor: IdeaPluginDescriptor
16 | get() = PluginManagerCore.getLoadedPlugins().single {
17 | (ApplicationManager.getApplication().isUnitTestMode && it.pluginId.idString == myTestPluginId) ||
18 | (ApplicationManager.getApplication().isUnitTestMode.not() && it.pluginClassLoader == classLoader)
19 | }
20 |
21 | val name: String
22 | get() = descriptor.name
23 |
24 | val installationFolder: File
25 | get() = descriptor.pluginPath.toFile()
26 |
27 | val info: PluginInfo?
28 | get() = try {
29 | getPluginInfoByDescriptor(descriptor)
30 | } catch (ex: Exception) {
31 | null
32 | }
33 |
34 | @TestOnly
35 | fun setTestPlugin(id: String) {
36 | myTestPluginId = id
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/datatypes/BinOp.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.datatypes
2 |
3 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
4 |
5 | class BinOp(
6 | private val left: String,
7 | private val right: String,
8 | private val op: String,
9 | private val leftType: String,
10 | private val rightType: String,
11 | private val parent: String,
12 | private val grandParent: String
13 | ) : DataType() {
14 | override val text: String = "$left $op $right"
15 |
16 | override fun vectorize(): FloatArray? {
17 | val vocab = CommonModelStorage.vocabulary
18 |
19 | return listOf(
20 | vocab.tokens[left] ?: return null,
21 | vocab.tokens[right] ?: return null,
22 | vocab.operators[op] ?: return null,
23 | vocab.types[leftType] ?: return null,
24 | vocab.types[rightType] ?: return null,
25 | vocab.nodeTypes[parent] ?: return null,
26 | vocab.nodeTypes[grandParent] ?: return null
27 | ).reduce(FloatArray::plus)
28 | }
29 |
30 | fun replaceOperator(newOp: String) = BinOp(left, right, newOp, leftType, rightType, parent, grandParent)
31 | }
32 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/datatypes/Call.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.datatypes
2 |
3 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
4 |
5 | class Call(
6 | private val callee: String,
7 | private val arguments: List,
8 | private val base: String,
9 | private val argumentTypes: List,
10 | private val parameters: List
11 | ) : DataType() {
12 | override val text: String = "$base.$callee(${arguments.joinToString(",")})"
13 |
14 | override fun vectorize(): FloatArray? {
15 | val vocab = CommonModelStorage.vocabulary
16 |
17 | val nameVector = vocab.tokens[callee] ?: return null
18 | val argVectors = arguments.map { arg -> vocab.tokens[arg] ?: return null }.reduce(FloatArray::plus)
19 | val baseVector = vocab.tokens[base] ?: FloatArray(200) { 0.0f }
20 | val typeVectors = argumentTypes.map { argType -> vocab.types[argType] ?: return null }.reduce(FloatArray::plus)
21 | val paramVectors = parameters.map { param -> vocab.tokens[param] ?: FloatArray(200) { 0.0f } }.reduce(FloatArray::plus)
22 |
23 | return nameVector + argVectors + baseVector + typeVectors + paramVectors
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/datatypes/DataType.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.datatypes
2 |
3 | abstract class DataType {
4 | abstract val text: String
5 | abstract fun vectorize(): FloatArray?
6 | }
7 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/error/DeepBugsErrorReporter.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.error
2 |
3 | import com.intellij.diagnostic.ITNReporter
4 |
5 | class DeepBugsErrorReporter : ITNReporter()
6 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/fus/DeepBugsEventLogger.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.fus
2 |
3 | import com.intellij.internal.statistic.eventLog.*
4 |
5 | object DeepBugsEventLogger {
6 | private val loggerProvider: StatisticsEventLoggerProvider = getEventLogProvider("DBP")
7 |
8 | val version: Int = loggerProvider.version
9 |
10 | fun log(group: EventLogGroup, action: String) {
11 | return loggerProvider.logger.log(group, action, false)
12 | }
13 |
14 | fun log(group: EventLogGroup, action: String, data: FeatureUsageData) {
15 | return loggerProvider.logger.log(group, action, data.build(), false)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/fus/DeepBugsEventLoggerProvider.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.fus
2 |
3 | import com.intellij.internal.statistic.eventLog.StatisticsEventLoggerProvider
4 | import com.intellij.internal.statistic.utils.StatisticsUploadAssistant
5 | import com.intellij.openapi.application.ApplicationManager
6 | import com.intellij.openapi.util.registry.Registry
7 |
8 | class DeepBugsEventLoggerProvider : StatisticsEventLoggerProvider("DBP", 1) {
9 | override fun isRecordEnabled(): Boolean =
10 | !ApplicationManager.getApplication().isUnitTestMode &&
11 | Registry.`is`("feature.usage.event.log.collect.and.upload") &&
12 | StatisticsUploadAssistant.isCollectAllowed()
13 |
14 | override fun isSendEnabled(): Boolean = isRecordEnabled() && StatisticsUploadAssistant.isSendAllowed()
15 | }
16 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/fus/collectors/counter/DeepBugsCounterCollector.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter
2 |
3 | import com.intellij.concurrency.JobScheduler
4 | import com.intellij.internal.statistic.eventLog.EventLogGroup
5 | import com.intellij.internal.statistic.eventLog.FeatureUsageData
6 | import com.intellij.openapi.project.Project
7 | import org.jetbrains.research.deepbugs.common.DeepBugsPlugin
8 | import org.jetbrains.research.deepbugs.common.ide.fus.DeepBugsEventLogger
9 | import org.slf4j.LoggerFactory
10 | import java.util.concurrent.TimeUnit
11 |
12 | object DeepBugsCounterCollector {
13 | private const val LOG_DELAY_MIN = 24 * 60
14 | private const val LOG_INITIAL_DELAY_MIN = 10
15 | private val LOG = LoggerFactory.getLogger(DeepBugsCounterCollector::class.java)
16 |
17 | private val eventGroup = EventLogGroup("dbp.count", DeepBugsEventLogger.version)
18 |
19 | init {
20 | JobScheduler.getScheduler().scheduleWithFixedDelay(
21 | { trackRegistered() },
22 | LOG_INITIAL_DELAY_MIN.toLong(),
23 | LOG_DELAY_MIN.toLong(),
24 | TimeUnit.MINUTES
25 | )
26 | }
27 |
28 | fun problemFound(project: Project, inspection: String, result: Float) = log("report") {
29 | addProject(project)
30 | addData("inspection", inspection)
31 | addData("result", result)
32 | }
33 |
34 | fun tokensMatched(project: Project, inspection: String, matched: Boolean) = log("tokens.matched") {
35 | addProject(project)
36 | addData("inspection", inspection)
37 | addData("matched", matched)
38 | }
39 |
40 | fun quickFixApplied(project: Project, quickFixId: String, cancelled: Boolean) = log("quickfix.applied") {
41 | addProject(project)
42 | addData("quickfix", quickFixId)
43 | addData("cancelled", cancelled)
44 | }
45 |
46 | fun checkDisabled(project: Project, total: Int) = log("check.disabled") {
47 | addProject(project)
48 | addData("total", total)
49 | }
50 |
51 | fun modelReset(total: Int) = log("model.reset") {
52 | addData("total", total)
53 | }
54 |
55 | private fun log(eventId: String, body: FeatureUsageData.() -> Unit) {
56 | return try {
57 | val data = FeatureUsageData()
58 | .addPluginInfo(DeepBugsPlugin.info ?: return)
59 | .apply(body)
60 | DeepBugsEventLogger.log(eventGroup, eventId, data)
61 | } catch (ex: Exception) {
62 | LOG.warn("Failed to get PluginInfo for ${DeepBugsPlugin.name}")
63 | }
64 | }
65 |
66 | private fun trackRegistered() = DeepBugsEventLogger.log(eventGroup, "registered")
67 | }
68 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/inspections/DeepBugsInspectionManager.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.inspections
2 |
3 | import com.intellij.psi.PsiElement
4 | import org.jetbrains.research.deepbugs.common.ide.inspections.specific.SpecificInspectionDescriptor
5 | import java.util.concurrent.ConcurrentHashMap
6 |
7 | object DeepBugsInspectionManager {
8 | private val specificDescriptors = ConcurrentHashMap.newKeySet()
9 |
10 | fun register(descriptor: SpecificInspectionDescriptor) = specificDescriptors.add(descriptor)
11 |
12 | fun isSpecific(element: PsiElement) = specificDescriptors.any { it.shouldProcess(element) }
13 | }
14 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/inspections/specific/SpecificInspectionDescriptor.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.inspections.specific
2 |
3 | import com.intellij.psi.PsiElement
4 |
5 | data class SpecificInspectionDescriptor(
6 | val shouldProcess: (PsiElement) -> Boolean
7 | )
8 |
9 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/msg/DeepBugsLifecycle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.msg
2 |
3 | import com.intellij.application.subscribe
4 | import com.intellij.openapi.application.ApplicationManager
5 | import com.intellij.util.messages.Topic
6 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
7 | import org.jetbrains.research.deepbugs.common.ide.ui.DeepBugsSettingsPanel
8 |
9 | interface DeepBugsLifecycle {
10 | companion object {
11 | private val topic = Topic.create("deepbugs_lifecycle", DeepBugsLifecycle::class.java)
12 | val publisher by lazy { ApplicationManager.getApplication().messageBus.syncPublisher(topic) }
13 |
14 | init {
15 | topic.subscribe(ApplicationManager.getApplication(), InspectionStateHandler)
16 | topic.subscribe(ApplicationManager.getApplication(), DeepBugsSettingsPanel)
17 | }
18 | }
19 |
20 | fun init(init: DeepBugsConfig.State)
21 |
22 | fun update(previous: DeepBugsConfig.State, new: DeepBugsConfig.State)
23 | }
24 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/msg/InspectionStateHandler.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.msg
2 |
3 | import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
4 | import com.intellij.openapi.project.ProjectManager
5 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
6 |
7 | object InspectionStateHandler : DeepBugsLifecycle {
8 | override fun init(init: DeepBugsConfig.State) {
9 | ProjectManager.getInstance().openProjects.forEach {
10 | DaemonCodeAnalyzer.getInstance(it).restart()
11 | }
12 | }
13 |
14 | override fun update(previous: DeepBugsConfig.State, new: DeepBugsConfig.State) {
15 | if (previous == new) return
16 | init(new)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/problem/BugDescriptor.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.problem
2 |
3 | import com.intellij.codeInspection.LocalQuickFix
4 | import com.intellij.codeInspection.ProblemDescriptorBase
5 | import com.intellij.codeInspection.ProblemHighlightType
6 | import com.intellij.psi.PsiElement
7 | import com.intellij.util.containers.toArray
8 |
9 | class BugDescriptor(element: PsiElement, description: String, onTheFly: Boolean, fixes: List = emptyList()) : ProblemDescriptorBase(
10 | element,
11 | element,
12 | description,
13 | fixes.toArray(LocalQuickFix.EMPTY_ARRAY),
14 | ProblemHighlightType.GENERIC_ERROR,
15 | false,
16 | null,
17 | true,
18 | onTheFly
19 | )
20 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/quickfixes/FlipFunctionArgumentsQuickFix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.quickfixes
2 |
3 | import com.intellij.codeInsight.intention.PriorityAction
4 | import com.intellij.codeInspection.LocalQuickFix
5 | import com.intellij.codeInspection.ProblemDescriptor
6 | import com.intellij.openapi.project.Project
7 | import com.intellij.psi.PsiElement
8 | import org.jetbrains.research.deepbugs.common.CommonResourceBundle
9 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
10 |
11 | abstract class FlipFunctionArgumentsQuickFix : LocalQuickFix, PriorityAction {
12 | override fun getName(): String = CommonResourceBundle.message("deepbugs.flip.arguments.quickfix")
13 |
14 | override fun getPriority(): PriorityAction.Priority = PriorityAction.Priority.HIGH
15 |
16 | protected abstract fun T.toArguments(): Pair
17 |
18 | @Suppress("UNCHECKED_CAST")
19 | override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
20 | val element = descriptor.psiElement as? T ?: return
21 |
22 | val (arg0, arg1) = element.toArguments()
23 |
24 | arg0.replace(arg1)
25 | arg1.replace(arg0)
26 |
27 | DeepBugsCounterCollector.quickFixApplied(project, "flip.arguments", cancelled = false)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/quickfixes/ReplaceBinOperatorQuickFix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.quickfixes
2 |
3 | import com.intellij.codeInsight.intention.PriorityAction
4 | import com.intellij.codeInsight.lookup.*
5 | import com.intellij.codeInsight.lookup.impl.LookupImpl
6 | import com.intellij.codeInspection.LocalQuickFix
7 | import com.intellij.codeInspection.ProblemDescriptor
8 | import com.intellij.ide.DataManager
9 | import com.intellij.openapi.actionSystem.CommonDataKeys
10 | import com.intellij.openapi.editor.Editor
11 | import com.intellij.openapi.project.Project
12 | import com.intellij.openapi.util.TextRange
13 | import org.jetbrains.research.deepbugs.common.CommonResourceBundle
14 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
15 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
16 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
17 | import kotlin.math.min
18 |
19 | class ReplaceBinOperatorQuickFix(
20 | private val data: BinOp,
21 | private val operatorRange: TextRange,
22 | private val threshold: Float,
23 | private val displayName: String,
24 | private val transform: (String) -> String = { it }
25 | ) : LocalQuickFix, PriorityAction {
26 | override fun getName(): String = if (lookups.size == 1) {
27 | CommonResourceBundle.message("deepbugs.replace.operator.single.quickfix", lookups.single().lookupString)
28 | } else {
29 | CommonResourceBundle.message("deepbugs.replace.operator.multiple.quickfix")
30 | }
31 |
32 | override fun getFamilyName(): String = displayName
33 |
34 | override fun getPriority(): PriorityAction.Priority = PriorityAction.Priority.HIGH
35 |
36 | override fun startInWriteAction(): Boolean = true
37 |
38 | fun isAvailable() = lookups.isNotEmpty()
39 |
40 | override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
41 | DataManager.getInstance().dataContextFromFocusAsync.onSuccess { context ->
42 | val editor: Editor = CommonDataKeys.EDITOR.getData(context) ?: return@onSuccess
43 |
44 | val endOff = min(operatorRange.endOffset, editor.document.textLength)
45 | editor.selectionModel.setSelection(operatorRange.startOffset, endOff)
46 |
47 | val lookup = LookupManager.getInstance(project)
48 | .createLookup(editor, lookups.toTypedArray(),"", LookupArranger.DefaultArranger())
49 | .setSelectionRemoval()
50 | .registerCollector() as LookupImpl
51 |
52 | lookup.items.singleOrNull()?.let {
53 | editor.document.replaceString(operatorRange.startOffset, endOff, it.lookupString)
54 | lookup.fireItemSelected(it, 0.toChar())
55 | } ?: lookup.showLookup()
56 | }
57 | }
58 |
59 | private val lookups: List by lazy {
60 | CommonModelStorage.vocabulary.operators.data.map {
61 | val newBinOp = data.replaceOperator(it.key).vectorize()
62 | val res = newBinOp?.let { op -> CommonModelStorage.common.binOperatorModel.predict(op) }
63 | it.key to res
64 | }.filter { it.second != null && it.second!! < threshold }
65 | .sortedBy { it.second }.take(5)
66 | .map { LookupElementBuilder.create(transform(it.first)) }
67 | }
68 |
69 | companion object {
70 | fun ReplaceBinOperatorQuickFix?.toLookups() = if (this == null) emptyArray() else lookups.map { it.lookupString }.toTypedArray()
71 |
72 | private fun Lookup.registerCollector(): Lookup {
73 | addLookupListener(
74 | object : LookupListener {
75 | override fun itemSelected(event: LookupEvent) = DeepBugsCounterCollector.quickFixApplied(project, "replace.operator", cancelled = false)
76 | override fun lookupCanceled(event: LookupEvent) = DeepBugsCounterCollector.quickFixApplied(project, "replace.operator", cancelled = true)
77 | }
78 | )
79 | return this
80 | }
81 |
82 | private fun Lookup.setSelectionRemoval(): Lookup {
83 | addLookupListener (
84 | object : LookupListener {
85 | override fun itemSelected(event: LookupEvent) = editor.selectionModel.removeSelection(false)
86 | }
87 | )
88 | return this
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/ui/DeepBugsConfigurable.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.ui
2 |
3 | import com.intellij.openapi.options.ConfigurableBase
4 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
5 |
6 | abstract class DeepBugsConfigurable(
7 | private val default: DeepBugsConfig.State,
8 | id: String,
9 | display: String
10 | ) : ConfigurableBase(id, display, null) {
11 | override fun createUi(): DeepBugsSettingsPanel = DeepBugsSettingsPanel(settings, default)
12 | }
13 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/ui/DeepBugsSettingsPanel.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.ui
2 |
3 | import com.intellij.openapi.options.ConfigurableUi
4 | import com.intellij.ui.layout.migLayout.createLayoutConstraints
5 | import net.miginfocom.layout.AC
6 | import net.miginfocom.layout.CC
7 | import net.miginfocom.swing.MigLayout
8 | import org.jetbrains.research.deepbugs.common.*
9 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
10 | import org.jetbrains.research.deepbugs.common.ide.msg.DeepBugsLifecycle
11 | import javax.swing.JButton
12 |
13 | class DeepBugsSettingsPanel(private val settings: DeepBugsConfig, private val default: DeepBugsConfig.State) : ConfigurableUi {
14 | companion object : DeepBugsLifecycle {
15 | private val resetButton = JButton(CommonResourceBundle.message("reset.button.text"))
16 |
17 | override fun init(init: DeepBugsConfig.State) {
18 | resetButton.isEnabled = init.userDisabledChecks.isNotEmpty()
19 | }
20 |
21 | override fun update(previous: DeepBugsConfig.State, new: DeepBugsConfig.State) {
22 | if (previous.userDisabledChecks == new.userDisabledChecks) return
23 |
24 | init(new)
25 | }
26 | }
27 |
28 | init {
29 | resetButton.addActionListener {
30 | DeepBugsCounterCollector.modelReset(settings.state.userDisabledChecks.size)
31 | settings.update(default)
32 | }
33 | }
34 |
35 |
36 | override fun getComponent() = panel(MigLayout(createLayoutConstraints(), AC().grow(), AC().index(1).grow())) {
37 | panel(MigLayout(createLayoutConstraints(), AC().grow()), constraint = CC().growX().wrap()) {
38 | add(wrapWithComment(resetButton, CommonResourceBundle.message("reset.button.comment")),
39 | CC().growX().width("100%").height("10%").alignY("top"))
40 | }
41 | }
42 |
43 | override fun apply(settings: DeepBugsConfig) = Unit
44 | override fun isModified(settings: DeepBugsConfig): Boolean = false
45 | override fun reset(settings: DeepBugsConfig) = Unit
46 | }
47 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/ide/ui/UiUtils.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.ide.ui
2 |
3 | import com.intellij.openapi.ui.panel.ComponentPanelBuilder
4 | import java.awt.*
5 | import javax.swing.JComponent
6 | import javax.swing.JPanel
7 |
8 | fun panel(layout: LayoutManager = BorderLayout(0, 0), body: JPanel.() -> Unit) = JPanel(layout).apply(body)
9 |
10 | fun Container.panel(
11 | layout: LayoutManager = BorderLayout(0, 0), constraint: Any,
12 | body: JPanel.() -> Unit
13 | ): JPanel = JPanel(layout).apply(body).also { add(it, constraint) }
14 |
15 | fun wrapWithComment(component: JComponent, comment: String) = ComponentPanelBuilder(component)
16 | .withComment(comment)
17 | .moveCommentRight()
18 | .resizeY(true)
19 | .createPanel()
20 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/model/CommonModelStorage.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.model
2 |
3 | import org.jetbrains.research.deepbugs.common.model.common.CommonModel
4 |
5 | object CommonModelStorage {
6 | val common: CommonModel by lazy { CommonModel() }
7 | val vocabulary: Vocabulary by lazy { Vocabulary() }
8 | }
9 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/model/ModelHandler.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.model
2 |
3 | import org.jetbrains.research.deepbugs.common.DeepBugsPlugin
4 | import org.jetbrains.research.deepbugs.common.utils.Cbor
5 | import org.jetbrains.research.deepbugs.common.utils.Mapping
6 | import org.jetbrains.research.keras.runner.deserializer.ModelLoader
7 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
8 | import java.io.File
9 |
10 | object ModelHandler {
11 | private val modelsRoot by lazy { File(DeepBugsPlugin.installationFolder, "models") }
12 |
13 | private fun getModule(module: String): File = File(modelsRoot, module)
14 |
15 | fun loadMapping(name: String): Mapping = Cbor.parse(File(modelsRoot, name).readBytes(), Mapping.serializer())
16 |
17 | fun loadModel(name: String, module: String): Perceptron? = try {
18 | ModelLoader.loadPerceptronModel(File(getModule(module), name))
19 | } catch (ex: Exception) {
20 | null
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/model/Vocabulary.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.model
2 |
3 | import org.jetbrains.research.deepbugs.common.utils.Mapping
4 |
5 | data class Vocabulary(
6 | val tokens: Mapping = ModelHandler.loadMapping("tokenToVector.cbor"),
7 | val operators: Mapping = ModelHandler.loadMapping("operatorToVector.cbor"),
8 | val types: Mapping = ModelHandler.loadMapping("typeToVector.cbor"),
9 | val nodeTypes: Mapping = ModelHandler.loadMapping("nodeTypeToVector.cbor")
10 | )
11 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/model/common/CommonModel.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.model.common
2 |
3 | import org.jetbrains.research.deepbugs.common.model.ModelHandler
4 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
5 |
6 | data class CommonModel(
7 | val binOperandModel: Perceptron = loadModel("binOperandDetectionModel.h5"),
8 | val binOperatorModel: Perceptron = loadModel("binOperatorDetectionModel.h5"),
9 | val swappedArgsModel: Perceptron = loadModel("swappedArgsDetectionModel.h5")
10 | ) {
11 | companion object {
12 | fun loadModel(model: String): Perceptron = ModelHandler.loadModel(model, "common")!!
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/utils/Cbor.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.utils
2 |
3 | import kotlinx.serialization.KSerializer
4 | import kotlinx.serialization.cbor.Cbor
5 |
6 | object Cbor {
7 | val cbor = Cbor()
8 |
9 | @Suppress("unused")
10 | inline fun bytes(value: T, serializer: KSerializer) = cbor.dump(serializer, value)
11 |
12 | inline fun parse(value: ByteArray, serializer: KSerializer) = cbor.load(serializer, value)
13 | }
14 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/org/jetbrains/research/deepbugs/common/utils/Mapping.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.common.utils
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class Mapping(val data: Map) {
7 | operator fun get(fieldName: String): FloatArray? = data[fieldName]
8 | }
9 |
--------------------------------------------------------------------------------
/common/src/main/resources/DeepBugsCommonBundle.properties:
--------------------------------------------------------------------------------
1 | platform.exception.message={0} is not supported on the current platform.
2 | reset.button.text=Reset to Default
3 | reset.button.comment=Enable all previously ignored bug detection rules
4 | deepbugs.replace.operator.multiple.quickfix=Replace operator with more appropriate
5 | deepbugs.replace.operator.single.quickfix=Change operator to “{0}”
6 | deepbugs.flip.arguments.quickfix=Fix order of arguments
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS='"-Xmx64m"'
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS="-Xmx64m"
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/js-plugin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.intellij.tasks.*
2 | import tanvd.kosogor.defaults.configureIdea
3 |
4 | group = rootProject.group
5 | version = rootProject.version
6 |
7 | intellij {
8 | pluginName = "DeepBugs for JavaScript"
9 | version = rootProject.intellij.version
10 | type = "IU"
11 | downloadSources = true
12 | setPlugins("JavaScriptLanguage", "CSS", "platform-images")
13 | }
14 |
15 | configureIdea {
16 | exclude += file("src/test/testData")
17 | }
18 |
19 | tasks.withType {
20 | from("${projectDir}/src/main/models") {
21 | into("${pluginName}/models")
22 | }
23 | }
24 |
25 | tasks.withType {
26 | jvmArgs("-Xmx1g", "-Didea.is.internal=true")
27 | }
28 |
29 | tasks.withType {
30 | useJUnit()
31 |
32 | jvmArgs("-Xmx1g", "-Didea.is.internal=true")
33 | testLogging {
34 | events("passed", "skipped", "failed")
35 | }
36 | }
37 |
38 | tasks.withType {
39 | sinceBuild("201")
40 | untilBuild("")
41 | }
42 |
43 | dependencies {
44 | implementation(project(":common"))
45 | implementation(project(":keras-runner"))
46 | }
47 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/JSDeepBugsConfig.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript
2 |
3 | import com.intellij.openapi.components.*
4 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
5 | import org.jetbrains.research.deepbugs.common.DeepBugsConfigHandler
6 |
7 | @State(name = "DeepBugsJS", storages = [Storage("deepbugs.js.xml")])
8 | class JSDeepBugsConfig : PersistentStateComponent, DeepBugsConfig(default) {
9 | companion object : DeepBugsConfigHandler() {
10 | override val instance: JSDeepBugsConfig by lazy { service() }
11 | override val default = State()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/JSResourceBundle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript
2 |
3 | import com.intellij.AbstractBundle
4 | import org.jetbrains.annotations.PropertyKey
5 | import java.util.*
6 |
7 | object JSResourceBundle {
8 | private const val BUNDLE_NAME = "DeepBugsJavaScriptBundle"
9 |
10 | private val bundle by lazy { ResourceBundle.getBundle(BUNDLE_NAME) }
11 |
12 | fun message(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg params: Any): String {
13 | return AbstractBundle.message(bundle!!, key, *params)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/datatypes/JSDataTypeUtils.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.datatypes
2 |
3 | import com.intellij.lang.javascript.psi.*
4 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
5 | import org.jetbrains.research.deepbugs.common.datatypes.Call
6 | import org.jetbrains.research.deepbugs.javascript.extraction.*
7 |
8 | fun JSBinaryExpression.collect(): BinOp? {
9 | val leftName = lOperand?.extractNodeName() ?: return null
10 | val rightName = rOperand?.extractNodeName() ?: return null
11 | val op = operationSign?.toString() ?: return null
12 | val leftType = lOperand?.extractNodeType() ?: return null
13 | val rightType = rOperand?.extractNodeType() ?: return null
14 | val parentNode = parent.javaClass.simpleName ?: ""
15 | val grandParentNode = parent.parent.javaClass.simpleName ?: ""
16 | return BinOp(leftName, rightName, op, leftType, rightType, parentNode, grandParentNode)
17 | }
18 |
19 | fun JSCallExpression.collect(): Call? {
20 | val callee = methodExpression as? JSReferenceExpression ?: return null
21 | val name = callee.extractNodeName() ?: return null
22 |
23 | val args = ArrayList()
24 | val argTypes = ArrayList()
25 | for (arg in arguments) {
26 | args.add(arg.extractNodeName() ?: return null)
27 | argTypes.add(arg.extractNodeType())
28 | }
29 |
30 | val base = extractNodeBase()
31 |
32 | val resolved = try {
33 | callee.multiResolve(false).asSequence().mapNotNull { it.element as? JSFunction }.firstOrNull()
34 | } catch (ex: Exception) {
35 | null
36 | }
37 |
38 | val params = resolved?.parameters?.toList()
39 | val paramNames = MutableList(args.size) { "" }
40 | paramNames.forEachIndexed { idx, _ ->
41 | paramNames[idx] = params?.getOrNull(idx)?.extractNodeName() ?: ""
42 | }
43 | return Call(name, args, base, argTypes, paramNames)
44 | }
45 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/extraction/JSExtraction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.extraction
2 |
3 | import com.intellij.lang.javascript.JSTokenTypes
4 | import com.intellij.lang.javascript.psi.*
5 | import com.intellij.psi.util.PsiTreeUtil
6 |
7 | fun String.asLiteralString() = "LIT:$this"
8 |
9 | fun String.asIdentifierString() = "ID:$this"
10 |
11 | @Suppress("ComplexMethod")
12 | fun JSElement.extractNodeName(): String? = when (this) {
13 | is JSLiteralExpression -> text.asLiteralString()
14 | is JSThisExpression -> text.asLiteralString()
15 | is JSReferenceExpression -> referenceName?.asIdentifierString()
16 | is JSPrefixExpression -> {
17 | val operand = expression as? JSLiteralExpression
18 | if (operand != null && operand.isNumericLiteral && operationSign == JSTokenTypes.MINUS)
19 | text.asLiteralString()
20 | else expression?.extractNodeName()
21 | }
22 | is JSCallExpression -> methodExpression?.extractNodeName()
23 | is JSParameter -> text.takeWhile { it != ':' }.asIdentifierString()
24 | is JSArrayLiteralExpression -> text.asIdentifierString()
25 | is JSIndexedPropertyAccessExpression ->
26 | PsiTreeUtil.getChildOfType(this, JSReferenceExpression::class.java)?.referenceName?.asIdentifierString()
27 | else -> null
28 | }
29 |
30 | @Suppress("ComplexMethod")
31 | fun JSElement.extractNodeType(): String = when (this) {
32 | is JSThisExpression -> "object"
33 | is JSLiteralExpression -> {
34 | when {
35 | value == null -> "null"
36 | isNumericLiteral -> "number"
37 | isStringLiteral -> "string"
38 | isRegExpLiteral -> "regex"
39 | isBooleanLiteral -> "boolean"
40 | else -> "unknown"
41 | }
42 | }
43 | is JSReferenceExpression ->
44 | if (node.elementType.toString() == JSTokenTypes.UNDEFINED_KEYWORD.toString()) "undefined" else "unknown"
45 | is JSPrefixExpression -> expression?.extractNodeType() ?: "unknown"
46 | else -> "unknown"
47 | }
48 |
49 | fun JSElement.extractNodeBase(): String = when (this) {
50 | is JSCallExpression -> (methodExpression as? JSReferenceExpression)?.extractNodeBase() ?: ""
51 | is JSReferenceExpression -> qualifier?.extractNodeName() ?: ""
52 | else -> ""
53 | }
54 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/base/JSDeepBugsBaseInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.base
2 |
3 | import com.intellij.codeInspection.ProblemDescriptor
4 | import com.intellij.codeInspection.ProblemsHolder
5 | import com.intellij.lang.javascript.inspections.JSInspection
6 | import com.intellij.lang.javascript.psi.JSElement
7 | import com.intellij.lang.javascript.psi.JSElementVisitor
8 | import org.jetbrains.research.deepbugs.common.datatypes.DataType
9 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
10 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
11 | import org.jetbrains.research.deepbugs.javascript.JSDeepBugsConfig
12 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.JSIgnoreExpressionQuickFix
13 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
14 |
15 | abstract class JSDeepBugsBaseInspection(private val threshold: Float) : JSInspection() {
16 | protected abstract val model: Perceptron?
17 |
18 | protected open fun skip(node: T): Boolean = false
19 |
20 | protected open fun createProblemDescriptor(node: T, data: V): ProblemDescriptor =
21 | BugDescriptor(node, createTooltip(node), myOnTheFly, listOf(JSIgnoreExpressionQuickFix(data, node.text)))
22 |
23 | protected abstract fun createTooltip(node: T, vararg params: String): String
24 |
25 | abstract inner class JSDeepBugsVisitor(private val holder: ProblemsHolder) : JSElementVisitor() {
26 | protected fun visit(node: T, collect: T.() -> V?) {
27 | if (skip(node)) return
28 | val data = node.collect() ?: return
29 | val vectorized = data.vectorize()
30 | DeepBugsCounterCollector.tokensMatched(holder.project, shortName, matched = vectorized == null)
31 | val result = model?.predict(vectorized ?: return) ?: return
32 | analyzeInspected(result, node, data)
33 | }
34 |
35 | private fun analyzeInspected(result: Float, node: T, data: V) {
36 | if (!JSDeepBugsConfig.isProblem(result, threshold, data)) return
37 | holder.registerProblem(createProblemDescriptor(node, data))
38 | DeepBugsCounterCollector.problemFound(holder.project, shortName, result)
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/base/JSDeepBugsBinExprInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.base
2 |
3 | import com.intellij.codeInspection.LocalInspectionToolSession
4 | import com.intellij.codeInspection.ProblemsHolder
5 | import com.intellij.lang.javascript.psi.JSBinaryExpression
6 | import com.intellij.psi.PsiElementVisitor
7 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
8 | import org.jetbrains.research.deepbugs.javascript.datatypes.collect
9 |
10 | abstract class JSDeepBugsBinExprInspection(threshold: Float = 0.8f) : JSDeepBugsBaseInspection(threshold) {
11 | override fun createVisitor(holder: ProblemsHolder, session: LocalInspectionToolSession): PsiElementVisitor = JSDeepBugsBinOpVisitor(holder)
12 |
13 | inner class JSDeepBugsBinOpVisitor(holder: ProblemsHolder) : JSDeepBugsVisitor(holder) {
14 | override fun visitJSBinaryExpression(node: JSBinaryExpression?) {
15 | visit(node ?: return) { node.collect() }
16 | super.visitJSBinaryExpression(node)
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/base/JSDeepBugsCallExprInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.base
2 |
3 | import com.intellij.codeInspection.LocalInspectionToolSession
4 | import com.intellij.codeInspection.ProblemsHolder
5 | import com.intellij.lang.javascript.psi.JSCallExpression
6 | import com.intellij.psi.PsiElementVisitor
7 | import org.jetbrains.research.deepbugs.common.datatypes.Call
8 | import org.jetbrains.research.deepbugs.javascript.datatypes.collect
9 |
10 | abstract class JSDeepBugsCallExprInspection(
11 | protected val requiredArgumentsNum: Int,
12 | threshold: Float = 0.8f
13 | ) : JSDeepBugsBaseInspection(threshold) {
14 | override fun createVisitor(holder: ProblemsHolder, session: LocalInspectionToolSession): PsiElementVisitor = JSDeepBugsCallVisitor(holder)
15 |
16 | inner class JSDeepBugsCallVisitor(holder: ProblemsHolder) : JSDeepBugsVisitor(holder) {
17 | override fun visitJSCallExpression(node: JSCallExpression?) {
18 | visit(node ?: return) { node.collect() }
19 | super.visitJSCallExpression(node)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/common/JSDeepBugsBinOperandInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.common
2 |
3 | import com.intellij.lang.javascript.psi.JSBinaryExpression
4 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
5 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
6 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.base.JSDeepBugsBinExprInspection
7 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
8 |
9 | class JSDeepBugsBinOperandInspection : JSDeepBugsBinExprInspection() {
10 | override val model: Perceptron?
11 | get() = CommonModelStorage.common.binOperandModel
12 |
13 | override fun createTooltip(node: JSBinaryExpression, vararg params: String): String =
14 | JSResourceBundle.message(
15 | "deepbugs.javascript.binary.operand.inspection.warning",
16 | node.lOperand?.text ?: "",
17 | node.rOperand?.text ?: ""
18 | )
19 |
20 | override fun getShortName() = "JSDeepBugsBinOperand"
21 | }
22 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/common/JSDeepBugsBinOperatorInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.common
2 |
3 | import com.intellij.codeInspection.ProblemDescriptor
4 | import com.intellij.lang.javascript.psi.JSBinaryExpression
5 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
6 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
7 | import org.jetbrains.research.deepbugs.common.ide.quickfixes.ReplaceBinOperatorQuickFix
8 | import org.jetbrains.research.deepbugs.common.ide.quickfixes.ReplaceBinOperatorQuickFix.Companion.toLookups
9 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
10 | import org.jetbrains.research.deepbugs.javascript.JSDeepBugsConfig
11 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
12 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.base.JSDeepBugsBinExprInspection
13 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.JSIgnoreExpressionQuickFix
14 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.utils.operators
15 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
16 |
17 | class JSDeepBugsBinOperatorInspection : JSDeepBugsBinExprInspection() {
18 | override val model: Perceptron?
19 | get() = CommonModelStorage.common.binOperatorModel
20 |
21 | override fun createProblemDescriptor(node: JSBinaryExpression, data: BinOp): ProblemDescriptor {
22 | val textRange = node.operationNode!!.textRange
23 | val replaceQuickFix = ReplaceBinOperatorQuickFix(data, textRange, JSDeepBugsConfig.get().quickFixesThreshold,
24 | JSResourceBundle.message("deepbugs.javascript.replace.operator.family")) { operators[it] ?: "" }.takeIf { it.isAvailable() }
25 | return BugDescriptor(
26 | node,
27 | createTooltip(node, *(replaceQuickFix.toLookups())),
28 | myOnTheFly,
29 | listOfNotNull(JSIgnoreExpressionQuickFix(data, node.text), replaceQuickFix)
30 | )
31 | }
32 |
33 | override fun createTooltip(node: JSBinaryExpression, vararg params: String): String {
34 | val operatorText = node.operationNode?.text ?: ""
35 | return params.singleOrNull()?.let {
36 | JSResourceBundle.message("deepbugs.javascript.binary.operator.inspection.warning.single", it, operatorText)
37 | } ?: JSResourceBundle.message("deepbugs.javascript.binary.operator.inspection.warning", operatorText)
38 | }
39 |
40 | override fun getShortName() = "JSDeepBugsBinOperator"
41 | }
42 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/common/JSDeepBugsSwappedArgsInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.common
2 |
3 | import com.intellij.codeInspection.ProblemDescriptor
4 | import com.intellij.lang.javascript.psi.JSCallExpression
5 | import org.jetbrains.research.deepbugs.common.datatypes.Call
6 | import org.jetbrains.research.deepbugs.common.ide.inspections.DeepBugsInspectionManager
7 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
8 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
9 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
10 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.base.JSDeepBugsCallExprInspection
11 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.JSFlipFunctionArgumentsQuickFix
12 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.JSIgnoreExpressionQuickFix
13 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
14 |
15 | open class JSDeepBugsSwappedArgsInspection : JSDeepBugsCallExprInspection(2) {
16 | override val model: Perceptron?
17 | get() = CommonModelStorage.common.swappedArgsModel
18 |
19 | override fun skip(node: JSCallExpression): Boolean {
20 | if (node.arguments.size != requiredArgumentsNum) return true
21 | return DeepBugsInspectionManager.isSpecific(node)
22 | }
23 |
24 | override fun createProblemDescriptor(node: JSCallExpression, data: Call): ProblemDescriptor =
25 | BugDescriptor(node, createTooltip(node), myOnTheFly, listOf(
26 | JSIgnoreExpressionQuickFix(data, node.text),
27 | JSFlipFunctionArgumentsQuickFix()
28 | ))
29 |
30 | override fun createTooltip(node: JSCallExpression, vararg params: String): String =
31 | JSResourceBundle.message("deepbugs.javascript.swapped.args.inspection.warning")
32 |
33 | override fun getShortName() = "JSDeepBugsSwappedArgs"
34 | }
35 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/specific/math/JSDeepBugsIncorrectArgMathInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.specific.math
2 |
3 | import com.intellij.lang.javascript.psi.JSCallExpression
4 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
5 | import org.jetbrains.research.deepbugs.javascript.model.specific.JSSpecificModel
6 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
7 |
8 | class JSDeepBugsIncorrectArgMathInspection : JSDeepBugsMathCallExprInspection(requiredArgsNum = 1, threshold = 0.72f) {
9 | override val model: Perceptron?
10 | get() = JSSpecificModel.math.incorrectArgModel
11 |
12 | override val ignore: Set = setOf("toString", "substring")
13 |
14 | override fun createTooltip(node: JSCallExpression, vararg params: String): String =
15 | JSResourceBundle.message(
16 | "deepbugs.javascript.math.incorrect.arg.inspection.warning",
17 | node.arguments.first().text
18 | )
19 |
20 | override fun getShortName() = "JSDeepBugsIncorrectArgMath"
21 | }
22 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/specific/math/JSDeepBugsMathCallExprInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.specific.math
2 |
3 | import com.intellij.lang.javascript.library.JSLibraryUtil
4 | import com.intellij.lang.javascript.psi.JSCallExpression
5 | import com.intellij.lang.javascript.psi.JSReferenceExpression
6 | import org.jetbrains.research.deepbugs.common.ide.inspections.DeepBugsInspectionManager
7 | import org.jetbrains.research.deepbugs.common.ide.inspections.specific.SpecificInspectionDescriptor
8 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.base.JSDeepBugsCallExprInspection
9 |
10 | abstract class JSDeepBugsMathCallExprInspection(requiredArgsNum: Int, threshold: Float = 0.8f) : JSDeepBugsCallExprInspection(requiredArgsNum, threshold) {
11 | init {
12 | DeepBugsInspectionManager.register(
13 | SpecificInspectionDescriptor { (it is JSCallExpression) && !skip(it) }
14 | )
15 | }
16 |
17 | protected open val libsToConsider: Set = emptySet()
18 | protected open val ignore: Set = emptySet()
19 |
20 | override fun skip(node: JSCallExpression): Boolean {
21 | if (node.arguments.size != requiredArgumentsNum) return true
22 | val call = node.methodExpression as? JSReferenceExpression ?: return true
23 | return ignore.contains(call.referenceName) || (!call.isBuiltIn() && !call.isLibCall())
24 | }
25 |
26 | private fun JSReferenceExpression.isLibCall(): Boolean {
27 | val resolvedFiles = try {
28 | multiResolve(false).mapNotNull { it.element?.containingFile }
29 | } catch (ex: Exception) {
30 | return false
31 | }
32 | val libs = resolvedFiles.mapNotNull { JSLibraryUtil.getLibraryFolder(it.virtualFile)?.name }
33 | return libsToConsider.intersect(libs).isNotEmpty()
34 | }
35 |
36 | companion object {
37 | private val modulesToConsider: Set = setOf("Math")
38 |
39 | private fun JSReferenceExpression.isBuiltIn(): Boolean {
40 | val first = qualifier?.text?.split('.')?.firstOrNull() ?: return false
41 | return modulesToConsider.contains(first)
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/inspections/specific/math/JSDeepBugsSwappedArgsMathInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.inspections.specific.math
2 |
3 | import com.intellij.codeInspection.ProblemDescriptor
4 | import com.intellij.lang.javascript.psi.JSCallExpression
5 | import org.jetbrains.research.deepbugs.common.datatypes.Call
6 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
7 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
8 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.JSFlipFunctionArgumentsQuickFix
9 | import org.jetbrains.research.deepbugs.javascript.ide.quickfixes.JSIgnoreExpressionQuickFix
10 | import org.jetbrains.research.deepbugs.javascript.model.specific.JSSpecificModel
11 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
12 |
13 | class JSDeepBugsSwappedArgsMathInspection : JSDeepBugsMathCallExprInspection(requiredArgsNum = 2) {
14 | override val model: Perceptron?
15 | get() = JSSpecificModel.math.swappedArgsModel
16 |
17 | override val libsToConsider: Set = setOf("mathjs")
18 | override val ignore: Set = setOf("min", "max")
19 |
20 | override fun createProblemDescriptor(node: JSCallExpression, data: Call): ProblemDescriptor =
21 | BugDescriptor(node, createTooltip(node), myOnTheFly, listOf(
22 | JSIgnoreExpressionQuickFix(data, node.text),
23 | JSFlipFunctionArgumentsQuickFix()
24 | ))
25 |
26 | override fun createTooltip(node: JSCallExpression, vararg params: String): String =
27 | JSResourceBundle.message("deepbugs.javascript.math.swapped.args.inspection.warning")
28 |
29 | override fun getShortName() = "JSDeepBugsSwappedArgsMath"
30 | }
31 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/quickfixes/JSFlipFunctionArgumentsQuickFix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.quickfixes
2 |
3 | import com.intellij.lang.javascript.psi.JSCallExpression
4 | import com.intellij.psi.PsiElement
5 | import org.jetbrains.research.deepbugs.common.ide.quickfixes.FlipFunctionArgumentsQuickFix
6 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
7 |
8 | class JSFlipFunctionArgumentsQuickFix : FlipFunctionArgumentsQuickFix() {
9 | override fun getFamilyName(): String = JSResourceBundle.message("deepbugs.javascript.flip.args.family")
10 |
11 | override fun JSCallExpression.toArguments(): Pair = Pair(arguments[0], arguments[1])
12 | }
13 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/quickfixes/JSIgnoreExpressionQuickFix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.quickfixes
2 |
3 | import com.intellij.codeInsight.intention.PriorityAction
4 | import com.intellij.codeInspection.LocalQuickFix
5 | import com.intellij.codeInspection.ProblemDescriptor
6 | import com.intellij.icons.AllIcons
7 | import com.intellij.openapi.command.undo.BasicUndoableAction
8 | import com.intellij.openapi.command.undo.UndoManager
9 | import com.intellij.openapi.project.Project
10 | import com.intellij.openapi.util.Iconable
11 | import org.jetbrains.research.deepbugs.common.datatypes.DataType
12 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
13 | import org.jetbrains.research.deepbugs.javascript.JSDeepBugsConfig
14 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
15 | import javax.swing.Icon
16 |
17 | class JSIgnoreExpressionQuickFix(private val expr: DataType, private val displayText: String) : LocalQuickFix, Iconable, PriorityAction {
18 | override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
19 | val ignore = object : BasicUndoableAction(descriptor.psiElement?.containingFile?.virtualFile) {
20 | override fun redo() = JSDeepBugsConfig.ignoreExpression(expr)
21 | override fun undo() = JSDeepBugsConfig.considerExpression(expr)
22 | }
23 | ignore.redo()
24 | DeepBugsCounterCollector.checkDisabled(project, JSDeepBugsConfig.get().userDisabledChecks.size)
25 | UndoManager.getInstance(project).undoableActionPerformed(ignore)
26 | }
27 |
28 | override fun getIcon(flags: Int): Icon = AllIcons.Actions.Cancel
29 | override fun getPriority(): PriorityAction.Priority = PriorityAction.Priority.LOW
30 |
31 | override fun getFamilyName(): String = JSResourceBundle.message("deepbugs.javascript.ignore.family")
32 | override fun getName(): String = JSResourceBundle.message("deepbugs.javascript.ignore.quickfix", displayText)
33 | }
34 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/quickfixes/utils/JSOperatorMap.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.quickfixes.utils
2 |
3 | import com.intellij.lang.javascript.JSTokenTypes
4 |
5 | val operators by lazy {
6 | hashMapOf(
7 | JSTokenTypes.AND.toString() to "&",
8 | JSTokenTypes.ANDAND.toString() to "&&",
9 | JSTokenTypes.AS_KEYWORD.toString() to "as",
10 | JSTokenTypes.COMMA.toString() to ",",
11 | JSTokenTypes.DIV.toString() to "/",
12 | JSTokenTypes.EQEQ.toString() to "==",
13 | JSTokenTypes.EQEQEQ.toString() to "===",
14 | JSTokenTypes.GE.toString() to ">=",
15 | JSTokenTypes.GT.toString() to ">",
16 | JSTokenTypes.GTGT.toString() to ">>",
17 | JSTokenTypes.GTGTGT.toString() to ">>>",
18 | JSTokenTypes.INSTANCEOF_KEYWORD.toString() to "instance of",
19 | JSTokenTypes.IN_KEYWORD.toString() to "in",
20 | JSTokenTypes.LE.toString() to "<=",
21 | JSTokenTypes.LT.toString() to "<",
22 | JSTokenTypes.LTLT.toString() to "<<",
23 | JSTokenTypes.MINUS.toString() to "-",
24 | JSTokenTypes.MULT.toString() to "*",
25 | JSTokenTypes.NE.toString() to "!=",
26 | JSTokenTypes.NEQEQ.toString() to "!==",
27 | JSTokenTypes.OR.toString() to "|",
28 | JSTokenTypes.OROR.toString() to "||",
29 | JSTokenTypes.PERC.toString() to "%",
30 | JSTokenTypes.PLUS.toString() to "+",
31 | JSTokenTypes.XOR.toString() to "^"
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/ide/ui/JSDeepBugsConfigurable.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.ide.ui
2 |
3 | import com.intellij.openapi.components.service
4 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
5 | import org.jetbrains.research.deepbugs.common.ide.ui.DeepBugsConfigurable
6 | import org.jetbrains.research.deepbugs.javascript.JSDeepBugsConfig
7 | import org.jetbrains.research.deepbugs.javascript.JSResourceBundle
8 |
9 | class JSDeepBugsConfigurable : DeepBugsConfigurable(
10 | JSDeepBugsConfig.default,
11 | "JSPluginConfig",
12 | JSResourceBundle.message("deepbugs.javascript.display")
13 | ) {
14 | override fun getSettings(): DeepBugsConfig = service()
15 | }
16 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/model/specific/JSSpecificModel.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.model.specific
2 |
3 | object JSSpecificModel {
4 | val math: MathModel by lazy { MathModel() }
5 | }
6 |
--------------------------------------------------------------------------------
/js-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/javascript/model/specific/MathModel.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript.model.specific
2 |
3 | import org.jetbrains.research.deepbugs.common.model.ModelHandler
4 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
5 |
6 | data class MathModel(
7 | val swappedArgsModel: Perceptron = loadModel("swappedArgsDetectionModelMath.h5"),
8 | val incorrectArgModel: Perceptron = loadModel("incorrectFuncArgDetectionModelMath.h5")
9 | ) {
10 | companion object {
11 | private fun loadModel(model: String): Perceptron = ModelHandler.loadModel(model, "math")!!
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/js-plugin/src/main/models/common/binOperandDetectionModel.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/common/binOperandDetectionModel.h5
--------------------------------------------------------------------------------
/js-plugin/src/main/models/common/binOperatorDetectionModel.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/common/binOperatorDetectionModel.h5
--------------------------------------------------------------------------------
/js-plugin/src/main/models/common/swappedArgsDetectionModel.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/common/swappedArgsDetectionModel.h5
--------------------------------------------------------------------------------
/js-plugin/src/main/models/math/incorrectFuncArgDetectionModelMath.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/math/incorrectFuncArgDetectionModelMath.h5
--------------------------------------------------------------------------------
/js-plugin/src/main/models/math/swappedArgsDetectionModelMath.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/math/swappedArgsDetectionModelMath.h5
--------------------------------------------------------------------------------
/js-plugin/src/main/models/nodeTypeToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/nodeTypeToVector.cbor
--------------------------------------------------------------------------------
/js-plugin/src/main/models/operatorToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/operatorToVector.cbor
--------------------------------------------------------------------------------
/js-plugin/src/main/models/tokenToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/tokenToVector.cbor
--------------------------------------------------------------------------------
/js-plugin/src/main/models/typeToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/js-plugin/src/main/models/typeToVector.cbor
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/DeepBugsJavaScriptBundle.properties:
--------------------------------------------------------------------------------
1 | deepbugs.javascript.binary.operator.inspection.warning=Possibly incorrect operator: “{0}”
2 | deepbugs.javascript.binary.operator.inspection.warning.single=Probably you meant “{0}” instead of “{1}”
3 | deepbugs.javascript.binary.operand.inspection.warning=Possibly incorrect operand: “{0}” or “{1}”
4 | deepbugs.javascript.swapped.args.inspection.warning=Possibly wrong order of function arguments
5 | deepbugs.javascript.math.swapped.args.inspection.warning=Possibly wrong order of math function arguments
6 | deepbugs.javascript.math.incorrect.arg.inspection.warning=Possibly incorrect argument in math function call: “{0}”
7 | deepbugs.javascript.ignore.family=DeepBugs for JavaScript: Ignore expression
8 | deepbugs.javascript.flip.args.family=DeepBugs for JavaScript: Fix order of arguments
9 | deepbugs.javascript.replace.operator.family=DeepBugs for JavaScript: Replace operator
10 | deepbugs.javascript.display=DeepBugs for JavaScript
11 | deepbugs.javascript.ignore.quickfix=Always ignore “{0}”
12 | deepbugs.javascript.group.name=Probable bugs
13 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | DeepBugs for JavaScript
3 | DeepBugsJavaScript
4 | JetBrains
5 | Finds potential bugs and code quality issues for JavaScript using deep learning models.
7 |
8 | Detects several types of bugs, including incorrect function arguments, incorrect comparison, and others, based on extracted code semantics.
9 |
10 | Deep learning models are inspired by DeepBugs.
11 |
12 | To configure, open Preferences/Settings | Tools | DeepBugs for JavaScript .
13 | ]]>
14 |
15 | 0.5
17 | Update for 201.* builds
18 |
19 | 0.4
20 |
21 | Support specific inspections for math (built-in Math object) function calls
22 |
23 | Misused function argument
24 | Incorrect order of function arguments (also available for mathjs library)
25 |
26 | Minor bug fixes
27 |
28 |
29 | 0.3
30 |
31 | Significantly reduce plugin size
32 | Add several quick-fixes for detected bugs
33 | Fully rework settings UI and inspections tooltips
34 | A lot of bug fixes and stability improvements
35 |
36 |
37 | 0.2
38 |
39 | Minor improvements
40 |
41 | ]]>
42 |
43 |
44 | com.intellij.modules.lang
45 | JavaScript
46 |
47 |
48 |
49 |
50 |
56 |
57 |
63 |
64 |
70 |
71 |
77 |
78 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/META-INF/pluginIcon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/inspectionDescriptions/JSDeepBugsBinOperand.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of binary operands (arguments of binary operations)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/inspectionDescriptions/JSDeepBugsBinOperator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of binary operators
4 |
5 |
6 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/inspectionDescriptions/JSDeepBugsIncorrectArgMath.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of math function arguments
4 |
5 |
6 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/inspectionDescriptions/JSDeepBugsSwappedArgs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of function arguments (specifically, their order)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/js-plugin/src/main/resources/inspectionDescriptions/JSDeepBugsSwappedArgsMath.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of math function arguments (specifically, their order)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/js-plugin/src/test/kotlin/org/jetbrains/research/deepbugs/javascript/DeepBugsTestBase.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript
2 |
3 | import com.intellij.testFramework.fixtures.BasePlatformTestCase
4 | import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
5 | import org.jetbrains.research.deepbugs.common.DeepBugsPlugin
6 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.common.*
7 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.specific.math.JSDeepBugsIncorrectArgMathInspection
8 | import org.jetbrains.research.deepbugs.javascript.ide.inspections.specific.math.JSDeepBugsSwappedArgsMathInspection
9 | import java.io.File
10 |
11 | abstract class DeepBugsTestBase : BasePlatformTestCase() {
12 | init {
13 | DeepBugsPlugin.setTestPlugin("DeepBugsJavaScript")
14 | }
15 |
16 | override fun getTestDataPath(): String {
17 | return File("src/test/testData").canonicalPath
18 | }
19 |
20 | override fun setUp() {
21 | super.setUp()
22 | myFixture.enableInspections(*inspectionTools)
23 | (myFixture as? CodeInsightTestFixtureImpl)?.canChangeDocumentDuringHighlighting(true)
24 | }
25 |
26 | protected open fun runHighlightTestForFile(file: String) {
27 | myFixture.configureByFile(file)
28 | myFixture.checkHighlighting(true, false, false)
29 | }
30 |
31 | companion object {
32 | val inspectionTools by lazy {
33 | arrayOf(
34 | JSDeepBugsBinOperandInspection(),
35 | JSDeepBugsBinOperatorInspection(),
36 | JSDeepBugsSwappedArgsInspection(),
37 | JSDeepBugsSwappedArgsMathInspection(),
38 | JSDeepBugsIncorrectArgMathInspection()
39 | )
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/js-plugin/src/test/kotlin/org/jetbrains/research/deepbugs/javascript/JSDeepBugsTest.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.javascript
2 |
3 | class JSDeepBugsTest : DeepBugsTestBase() {
4 | fun `test bin operand`() {
5 | runHighlightTestForFile("testIncorrectBinOperandJS.js")
6 | }
7 |
8 | fun `test bin operator`() {
9 | runHighlightTestForFile("testIncorrectBinOperatorJS.js")
10 | }
11 |
12 | fun `test swapped arguments`() {
13 | runHighlightTestForFile("testSwappedArgumentsJS.js")
14 | }
15 |
16 | fun `test swapped arguments math`() {
17 | runHighlightTestForFile("testSwappedArgumentsMathJS.js")
18 | }
19 |
20 | fun `test incorrect argument math`() {
21 | runHighlightTestForFile("testIncorrectArgumentMathJS.js")
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/js-plugin/src/test/testData/testIncorrectArgumentMathJS.js:
--------------------------------------------------------------------------------
1 | let res1 = Math.sin(90) ;
2 |
3 | let txt = "text"
4 | let res2 = Math.ceil(txt) ;
5 |
6 | let rad = Math.PI / 2
7 | let res3 = Math.cos(rad)
8 |
--------------------------------------------------------------------------------
/js-plugin/src/test/testData/testIncorrectBinOperandJS.js:
--------------------------------------------------------------------------------
1 | function adder1(base) {
2 | base = Number(base);
3 | for (let j = 1; j < arguments ; j++) {
4 | base += Number(arguments[j]);
5 | }
6 | return base;
7 | }
8 |
9 | function adder2(base) {
10 | base = Number(base);
11 | for (let j = 1; j < arguments.length; j++) {
12 | base += Number(arguments[j]);
13 | }
14 | return base;
15 | }
16 |
17 |
18 | let x = 1;
19 | let y = 2;
20 | let height = 3;
21 |
22 | let res1 = height - x ;
23 | let res2 = height - y;
24 |
--------------------------------------------------------------------------------
/js-plugin/src/test/testData/testIncorrectBinOperatorJS.js:
--------------------------------------------------------------------------------
1 | function adder1(base) {
2 | base = Number(base);
3 | for (let i = 1; i <= arguments.length ; i++) {
4 | base += Number(arguments[i]);
5 | }
6 | return base;
7 | }
8 |
9 | function adder2(base) {
10 | base = Number(base);
11 | for (let i = 1; i < arguments.length; i++) {
12 | base += Number(arguments[i]);
13 | }
14 | return base;
15 | }
16 |
17 |
18 | let text = 1;
19 | let str = 2;
20 |
21 | text / str ;
22 | text + str;
23 |
--------------------------------------------------------------------------------
/js-plugin/src/test/testData/testSwappedArgumentsJS.js:
--------------------------------------------------------------------------------
1 | let x = 1;
2 | let y = 2;
3 | function setSize(xx, yy) {
4 | x = xx;
5 | y = yy;
6 | }
7 |
8 | let width = 5;
9 | let height = 10;
10 | setSize(width, height);
11 | setSize(height, width) ;
12 |
13 |
14 | let promise = new Promise((resolve, reject) => {
15 | if (Math.random() * 100 < 90) {
16 | resolve('Success');
17 | }
18 | reject(new Error('Error'));
19 | });
20 |
21 | let onSuccess = (resolvedValue) => console.log(resolvedValue);
22 | let onError = (error) => console.log(error);
23 |
24 | promise.then(onError, onSuccess) ;
25 | promise.then(onSuccess, onError);
26 |
--------------------------------------------------------------------------------
/js-plugin/src/test/testData/testSwappedArgumentsMathJS.js:
--------------------------------------------------------------------------------
1 | let x = 1;
2 | let y = 2;
3 | Math.atan2(x, y) ;
4 |
--------------------------------------------------------------------------------
/keras-runner/build.gradle.kts:
--------------------------------------------------------------------------------
1 | group = "org.jetbrains.research"
2 | version = rootProject.version
3 |
4 | intellij {
5 | version = rootProject.intellij.version
6 | }
7 |
8 | dependencies {
9 | implementation("io.jhdf", "jhdf", "0.5.3") {
10 | // to avoid conflict with the dependency already included in IntelliJ Platform
11 | exclude("org.slf4j")
12 | }
13 | api("scientifik", "kmath-core-jvm", "0.1.3") {
14 | exclude("org.jetbrains.kotlin")
15 | }
16 | implementation("org.jetbrains.kotlinx", "kotlinx-serialization-runtime", "0.20.0") {
17 | exclude("org.jetbrains.kotlin")
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/ModelLoader.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer
2 |
3 | import io.jhdf.HdfFile
4 | import io.jhdf.api.Dataset
5 | import org.jetbrains.research.keras.runner.deserializer.json.ModelConfig
6 | import org.jetbrains.research.keras.runner.deserializer.json.ModelScheme
7 | import org.jetbrains.research.keras.runner.nn.layer.Layer
8 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
9 | import java.io.File
10 |
11 | @Suppress("UNCHECKED_CAST")
12 | object ModelLoader {
13 | fun loadPerceptronModel(model: File): Perceptron {
14 | val (config, layers) = importSequentialModelParameters(model)
15 | config as ModelConfig.Sequential
16 | return Perceptron.create(config.name, layers, config.batchInputShape)
17 | }
18 |
19 | private fun importSequentialModelParameters(model: File): Pair>> {
20 | val hdf = HdfFile(model)
21 |
22 | val config = importModelConfig(hdf)
23 | val layers = importSequentialModelLayers(hdf, config.config)
24 |
25 | return config.config to layers
26 | }
27 |
28 | private fun importSequentialModelLayers(hdf: HdfFile, config: ModelConfig) = config.layers.mapNotNull { layer ->
29 | val layerWeights = hdf.getByPath("model_weights/${layer.config.name}")
30 | val weightNames = (layerWeights.getAttribute("weight_names").data as? Array)?.filterNotNull()
31 |
32 | val (weights, biases) = weightNames?.map { weight ->
33 | val data = hdf.getByPath("model_weights/${layer.config.name}/$weight") as Dataset
34 | weight to data.data.toMatrix()
35 | }?.partition { !it.first.contains("bias") } ?: null to null
36 |
37 | val params = Layer.Parameters(
38 | weights?.map { it.second }?.singleOrNull(),
39 | biases?.map { it.second }?.singleOrNull()
40 | )
41 | Layer.create(layer, params)
42 | }
43 |
44 | private fun importModelConfig(hdf: HdfFile): ModelScheme {
45 | val configString = hdf.getAttribute("model_config").data as String
46 | return ModelScheme.parse(configString)
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/Utils.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer
2 |
3 | import scientifik.kmath.linear.VirtualMatrix
4 | import scientifik.kmath.linear.transpose
5 | import scientifik.kmath.structures.Matrix
6 | import java.lang.IllegalStateException
7 |
8 | internal inline fun List.toDoubleList(): List = map { it.toDouble() }
9 |
10 | internal fun FloatArray.toDoubleList() = asList().toDoubleList()
11 | internal fun Array.toDoubleList() = map { it.toDoubleList() }
12 |
13 | @Suppress("UNCHECKED_CAST")
14 | internal inline fun T.toMatrix(): Matrix<*> = when (this) {
15 | is FloatArray -> VirtualMatrix(rowNum = size, colNum = 1, generator = { i, _ -> this[i] }).transpose()
16 | is Array<*> -> {
17 | this as Array
18 | VirtualMatrix(rowNum = size, colNum = this[0].size, generator = { i, j -> this[i][j] }).transpose()
19 | }
20 | else -> throw IllegalStateException("Cannot cast ${T::class} to matrix")
21 | }
22 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/json/ActivationType.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer.json
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | @Suppress("EnumEntryName")
7 | enum class ActivationType {
8 | relu,
9 | sigmoid
10 | }
11 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/json/LayerConfig.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer.json
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | @Suppress("PropertyName")
7 | sealed class LayerConfig {
8 | abstract val name: String
9 | abstract val trainable: Boolean
10 | abstract val batch_input_shape: List?
11 | abstract val dtype: String?
12 |
13 | @Serializable
14 | data class Dense(
15 | override val name: String,
16 | override val trainable: Boolean,
17 | override val batch_input_shape: List? = null,
18 | override val dtype: String? = null,
19 | val units: Int,
20 | val activation: ActivationType,
21 | val use_bias: Boolean
22 | ) : LayerConfig()
23 |
24 | @Serializable
25 | data class Dropout(
26 | override val name: String,
27 | override val trainable: Boolean,
28 | override val batch_input_shape: List? = null,
29 | override val dtype: String? = null,
30 | val rate: Double
31 | ) : LayerConfig()
32 | }
33 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/json/LayerScheme.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer.json
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import kotlinx.serialization.Transient
6 |
7 | @Serializable
8 | sealed class LayerScheme {
9 | abstract val type: Type
10 | abstract val config: LayerConfig
11 |
12 | @Serializable
13 | @SerialName("Dense")
14 | @Suppress("UNUSED")
15 | data class DenseLayerScheme(
16 | @Transient override val type: Type = Type.DENSE,
17 | override val config: LayerConfig.Dense
18 | ) : LayerScheme()
19 |
20 | @Serializable
21 | @SerialName("Dropout")
22 | @Suppress("UNUSED")
23 | data class DropoutLayerScheme(
24 | @Transient override val type: Type = Type.DROPOUT,
25 | override val config: LayerConfig.Dropout
26 | ) : LayerScheme()
27 |
28 | enum class Type {
29 | DENSE,
30 | DROPOUT
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/json/ModelConfig.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer.json
2 |
3 | import kotlinx.serialization.Serializable
4 | import kotlinx.serialization.Transient
5 |
6 | @Serializable
7 | sealed class ModelConfig {
8 | abstract val name: String
9 | abstract val layers: List
10 |
11 | @Serializable
12 | data class Sequential(
13 | override val name: String,
14 | override val layers: List
15 | ) : ModelConfig() {
16 | @Transient
17 | val batchInputShape = layers.first().config.batch_input_shape!!.filterNotNull()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/deserializer/json/ModelScheme.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.deserializer.json
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import kotlinx.serialization.json.Json
6 | import kotlinx.serialization.json.JsonConfiguration
7 |
8 | @Serializable
9 | sealed class ModelScheme {
10 | abstract val config: ModelConfig
11 |
12 | @Serializable
13 | @SerialName("Sequential")
14 | @Suppress("UNUSED")
15 | data class SequentialScheme(override val config: ModelConfig.Sequential) : ModelScheme()
16 |
17 | companion object {
18 | private val json = Json(configuration = JsonConfiguration.Stable.copy(ignoreUnknownKeys = true, classDiscriminator = "class_name"))
19 |
20 | fun parse(config: String) = json.parse(serializer(), config)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/activation/ActivatableVector.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.activation
2 |
3 | import scientifik.kmath.linear.*
4 | import scientifik.kmath.structures.Buffer
5 |
6 | class ActivatableVector(size: Int) {
7 | var values: RealMatrix = BufferMatrix(size, 1, Buffer.auto(size) { 0.0 })
8 | private set
9 |
10 | private var notActivatedValues: RealMatrix? = null
11 |
12 | fun activate(func: ActivationFunction) {
13 | if (notActivatedValues == null) notActivatedValues = values
14 | values = func(notActivatedValues!!.asPoint())
15 | }
16 |
17 | fun forward(weights: RealMatrix, bias: RealMatrix?, x: RealMatrix): RealMatrix {
18 | var res = weights.dot(x)
19 | if (bias != null) res = MatrixContext.real.add(res, bias.transpose())
20 | notActivatedValues = res
21 | return res
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/activation/ActivationFunction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.activation
2 |
3 | import org.jetbrains.research.keras.runner.deserializer.json.ActivationType
4 | import scientifik.kmath.linear.BufferMatrix
5 | import scientifik.kmath.linear.Point
6 | import scientifik.kmath.linear.RealMatrix
7 | import scientifik.kmath.structures.asBuffer
8 | import scientifik.kmath.structures.asIterable
9 | import kotlin.math.exp
10 | import kotlin.math.max
11 |
12 | sealed class ActivationFunction(private val func: (Double) -> Double) {
13 | operator fun invoke(array: Point): RealMatrix {
14 | return BufferMatrix(array.size, 1, array.asIterable().map(func).asBuffer())
15 | }
16 |
17 | object ReLU : ActivationFunction(func = { x -> max(0.0, x) })
18 | object Sigmoid : ActivationFunction(func = { x -> 1.0 / (1.0 + exp(-x)) })
19 |
20 | companion object {
21 | operator fun get(type: ActivationType) = when (type) {
22 | ActivationType.relu -> ReLU
23 | ActivationType.sigmoid -> Sigmoid
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/layer/ActivatableLayer.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.layer
2 |
3 | import org.jetbrains.research.keras.runner.nn.activation.ActivationFunction
4 | import scientifik.kmath.structures.NDStructure
5 |
6 | abstract class ActivatableLayer>(name: String, params: Parameters) : Layer(name, params) {
7 | protected abstract val activationFunction: ActivationFunction
8 |
9 | abstract fun activate()
10 | }
11 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/layer/Layer.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.layer
2 |
3 | import org.jetbrains.research.keras.runner.deserializer.json.LayerConfig
4 | import org.jetbrains.research.keras.runner.deserializer.json.LayerScheme
5 | import org.jetbrains.research.keras.runner.nn.activation.ActivationFunction
6 | import org.jetbrains.research.keras.runner.nn.layer.dense.DenseLayer
7 | import org.jetbrains.research.keras.runner.nn.layer.dense.DenseParameters
8 | import scientifik.kmath.structures.NDStructure
9 |
10 | abstract class Layer>(val name: String, val params: Parameters) {
11 | data class Parameters>(val weights: T?, val biases: T?)
12 |
13 | companion object {
14 | @Suppress("UNCHECKED_CAST")
15 | fun create(config: LayerScheme, params: Parameters<*>) = when (config.type) {
16 | LayerScheme.Type.DENSE -> DenseLayer(
17 | name = config.config.name,
18 | params = params as DenseParameters,
19 | activationFunction = ActivationFunction[(config.config as LayerConfig.Dense).activation]
20 | )
21 | LayerScheme.Type.DROPOUT -> null
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/layer/dense/DenseLayer.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.layer.dense
2 |
3 | import org.jetbrains.research.keras.runner.nn.activation.ActivatableVector
4 | import org.jetbrains.research.keras.runner.nn.activation.ActivationFunction
5 | import org.jetbrains.research.keras.runner.nn.layer.ActivatableLayer
6 | import scientifik.kmath.linear.BufferMatrix
7 | import scientifik.kmath.linear.Point
8 | import scientifik.kmath.structures.Matrix
9 |
10 | class DenseLayer(
11 | name: String,
12 | params: DenseParameters,
13 | override val activationFunction: ActivationFunction
14 | ) : ActivatableLayer>(name, params) {
15 |
16 | lateinit var inputArray: Point
17 | var outputArray: ActivatableVector = ActivatableVector(params.weights?.colNum ?: 0)
18 |
19 | override fun activate() {
20 | outputArray.forward(
21 | weights = params.weights!!,
22 | bias = params.biases,
23 | x = BufferMatrix(inputArray.size, 1, inputArray)
24 | )
25 | outputArray.activate(activationFunction)
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/layer/dense/DenseParameters.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.layer.dense
2 |
3 | import org.jetbrains.research.keras.runner.nn.layer.Layer
4 | import scientifik.kmath.linear.RealMatrix
5 |
6 | typealias DenseParameters = Layer.Parameters
7 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/model/Model.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.model
2 |
3 | abstract class Model(val name: String) {
4 | abstract fun predict(input: T): V?
5 | }
6 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/model/sequential/Perceptron.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.model.sequential
2 |
3 | import org.jetbrains.research.keras.runner.nn.layer.Layer
4 | import org.jetbrains.research.keras.runner.nn.layer.dense.DenseLayer
5 | import scientifik.kmath.linear.Point
6 | import scientifik.kmath.linear.asPoint
7 |
8 | open class Perceptron(
9 | name: String,
10 | override val layers: List,
11 | batchInputShape: List
12 | ) : SequentialModel(name, layers, batchInputShape) {
13 | companion object {
14 | @Suppress("UNCHECKED_CAST")
15 | fun create(name: String, layers: List>, batchInputShape: List?): Perceptron {
16 | require(batchInputShape != null) { "Model input shape is unspecified" }
17 | require(batchInputShape.filterNotNull().size == 1) { "Input should be one-dimensional" }
18 |
19 | layers as List
20 |
21 | return Perceptron(name, layers, batchInputShape)
22 | }
23 | }
24 |
25 | override fun predict(input: FloatArray): Float {
26 | require(batchInputShape!!.filterNotNull().single() == input.size) { "Unmatched input shapes" }
27 |
28 | layers.first().let {
29 | it.inputArray = Point.real(input.size) { i -> input[i].toDouble() }
30 | it.activate()
31 | }
32 |
33 | layers.zipWithNext { prev, cur ->
34 | cur.inputArray = prev.outputArray.values.asPoint()
35 | cur.activate()
36 | }
37 |
38 | return layers.last().outputArray.values[0, 0].toFloat()
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/keras-runner/src/main/kotlin/org/jetbrains/research/keras/runner/nn/model/sequential/SequentialModel.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.keras.runner.nn.model.sequential
2 |
3 | import org.jetbrains.research.keras.runner.nn.layer.Layer
4 | import org.jetbrains.research.keras.runner.nn.model.Model
5 |
6 | abstract class SequentialModel(
7 | name: String,
8 | protected open val layers: List>,
9 | val batchInputShape: List? = null
10 | ) : Model(name)
11 |
--------------------------------------------------------------------------------
/py-plugin/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.intellij.tasks.*
2 | import tanvd.kosogor.defaults.configureIdea
3 |
4 | group = rootProject.group
5 | version = rootProject.version
6 |
7 | intellij {
8 | pluginName = "DeepBugs for Python"
9 | version = rootProject.intellij.version
10 | type = "IC"
11 | downloadSources = true
12 | setPlugins("PythonCore:201.6668.13", "java")
13 | }
14 |
15 | configureIdea {
16 | exclude += file("src/test/testData")
17 | }
18 |
19 | tasks.withType {
20 | from("${projectDir}/src/main/models") {
21 | into("${pluginName}/models")
22 | }
23 | }
24 |
25 | tasks.withType {
26 | jvmArgs("-Xmx1g", "-Didea.is.internal=true")
27 | }
28 |
29 | tasks.withType {
30 | useJUnit()
31 |
32 | testLogging {
33 | events("passed", "skipped", "failed")
34 | }
35 | }
36 |
37 | tasks.withType {
38 | sinceBuild("201")
39 | untilBuild("")
40 | }
41 |
42 | dependencies {
43 | implementation(project(":common"))
44 | implementation(project(":keras-runner"))
45 | }
46 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/PyDeepBugsConfig.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python
2 |
3 | import com.intellij.openapi.components.*
4 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
5 | import org.jetbrains.research.deepbugs.common.DeepBugsConfigHandler
6 |
7 | @State(name = "DeepBugsPy", storages = [Storage("deepbugs.py.xml")])
8 | class PyDeepBugsConfig : PersistentStateComponent, DeepBugsConfig(default) {
9 | companion object : DeepBugsConfigHandler() {
10 | override val instance: PyDeepBugsConfig by lazy { service() }
11 | override val default = State()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/PyResourceBundle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python
2 |
3 | import com.intellij.AbstractBundle
4 | import org.jetbrains.annotations.PropertyKey
5 | import java.util.*
6 |
7 | object PyResourceBundle {
8 | private const val BUNDLE_NAME = "DeepBugsPythonBundle"
9 |
10 | private val bundle by lazy { ResourceBundle.getBundle(BUNDLE_NAME) }
11 |
12 | fun message(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String, vararg params: Any): String {
13 | return AbstractBundle.message(bundle!!, key, *params)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/datatypes/PyDataTypeUtils.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.datatypes
2 |
3 | import com.jetbrains.python.psi.PyBinaryExpression
4 | import com.jetbrains.python.psi.PyCallExpression
5 | import com.jetbrains.python.psi.resolve.PyResolveContext
6 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
7 | import org.jetbrains.research.deepbugs.common.datatypes.Call
8 | import org.jetbrains.research.deepbugs.python.extraction.*
9 |
10 | fun PyCallExpression.collect(): Call? {
11 | val name = callee?.extractNodeName() ?: return null
12 |
13 | val args = ArrayList()
14 | val argTypes = ArrayList()
15 | for (arg in arguments) {
16 | args.add(arg.extractNodeName() ?: return null)
17 | argTypes.add(arg.extractNodeType())
18 | }
19 |
20 | val base = extractNodeBase()
21 |
22 | val resolved = multiResolveCalleeFunction(PyResolveContext.defaultContext()).firstOrNull()
23 | var params = resolved?.parameterList?.parameters?.toList()
24 | if (!params.isNullOrEmpty() && params.first().isSelf && params.size > args.size)
25 | params = params.drop(1)
26 | val paramNames = MutableList(args.size) { "" }
27 | paramNames.forEachIndexed { idx, _ ->
28 | paramNames[idx] = params?.getOrNull(idx)?.extractNodeName() ?: ""
29 | }
30 | return Call(name, args, base, argTypes, paramNames)
31 | }
32 |
33 | fun PyBinaryExpression.collect(): BinOp? {
34 | val leftName = leftExpression?.extractNodeName() ?: return null
35 | val rightName = rightExpression?.extractNodeName() ?: return null
36 | val op = extractOperatorText() ?: return null
37 | val leftType = leftExpression?.extractNodeType() ?: return null
38 | val rightType = rightExpression?.extractNodeType() ?: return null
39 | val parentNode = parent.javaClass.simpleName ?: ""
40 | val grandParentNode = parent.parent.javaClass.simpleName ?: ""
41 | return BinOp(leftName, rightName, op, leftType, rightType, parentNode, grandParentNode)
42 | }
43 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/extraction/PyExtraction.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.extraction
2 |
3 | import com.intellij.openapi.util.TextRange
4 | import com.intellij.psi.PsiElement
5 | import com.intellij.psi.PsiWhiteSpace
6 | import com.intellij.psi.util.siblings
7 | import com.jetbrains.python.*
8 | import com.jetbrains.python.psi.*
9 |
10 | fun String.asLiteralString() = "LIT:$this"
11 |
12 | fun String.asIdentifierString() = "ID:$this"
13 |
14 | @Suppress("ComplexMethod")
15 | fun PyElement.extractNodeName(): String? = when (this) {
16 | is PyNumericLiteralExpression -> text.asLiteralString()
17 | is PyStringLiteralExpression -> stringValue.asLiteralString()
18 | is PyBoolLiteralExpression -> text.asLiteralString()
19 | is PyNoneLiteralExpression -> text.asLiteralString()
20 | is PyReferenceExpression -> referencedName?.asIdentifierString()
21 | is PyPrefixExpression -> {
22 | if (operator == PyTokenTypes.MINUS && operand is PyNumericLiteralExpression) text.asLiteralString()
23 | operand?.extractNodeName()
24 | }
25 | is PyCallExpression -> callee?.extractNodeName()
26 | is PySubscriptionExpression -> operand.extractNodeName()
27 | is PyLambdaExpression -> PyNames.LAMBDA.asIdentifierString()
28 | is PyParameter -> text.substringBefore(':').substringBefore('=').asIdentifierString()
29 | else -> null
30 | }
31 |
32 | @Suppress("ComplexMethod")
33 | fun PyElement.extractNodeType(): String = when (this) {
34 | is PyNumericLiteralExpression -> "number"
35 | is PyStringLiteralExpression -> "string"
36 | is PyBoolLiteralExpression -> "boolean"
37 | is PyNoneLiteralExpression -> "none"
38 | is PyReferenceExpression -> when (referencedName) {
39 | PyNames.CANONICAL_SELF -> "object"
40 | else -> "unknown"
41 | }
42 | is PyPrefixExpression -> operand?.extractNodeType() ?: "unknown"
43 | is PyLambdaExpression -> "lambda"
44 | else -> "unknown"
45 | }
46 |
47 | fun PyElement.extractNodeBase(): String = when (this) {
48 | is PyCallExpression -> (callee as? PyReferenceExpression)?.extractNodeBase() ?: ""
49 | is PyReferenceExpression -> qualifier?.extractNodeName() ?: ""
50 | is PySubscriptionExpression -> operand.extractNodeName() ?: ""
51 | else -> ""
52 | }
53 |
54 | fun PyBinaryExpression.extractOperatorText(): String? {
55 | operatorRange ?: return null
56 | if (operatorRange!!.first == operatorRange!!.second) return operatorRange!!.first.text
57 |
58 | return findOperatorElements().toList().asReversed().joinToString(" ") { it.text }
59 | }
60 |
61 | fun PyBinaryExpression.findOperatorTextRange(): TextRange? {
62 | operatorRange ?: return null
63 | return TextRange(operatorRange!!.first.textRange.startOffset, operatorRange!!.second.textRange.endOffset)
64 | }
65 |
66 | private fun PyBinaryExpression.findOperatorElements(): Sequence {
67 | operatorRange ?: emptySequence()
68 | if (operatorRange!!.first == operatorRange!!.second) return sequenceOf(operatorRange!!.first)
69 |
70 | val siblings = rightExpression?.prevSibling?.siblings(forward = false) ?: emptySequence()
71 | return siblings.takeWhile { it != operatorRange!!.first.prevSibling }.filter { it !is PsiWhiteSpace }
72 | }
73 |
74 | private val PyBinaryExpression.operatorRange: Pair?
75 | get() {
76 | val firstElement = psiOperator ?: return null
77 | val lastElement = rightExpression?.prevSibling?.siblings(forward = false)?.firstOrNull { it !is PsiWhiteSpace }
78 | return firstElement to (lastElement ?: firstElement)
79 | }
80 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/inspections/PyDeepBugsBinOperandInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.inspections
2 |
3 | import com.jetbrains.python.psi.PyBinaryExpression
4 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
5 | import org.jetbrains.research.deepbugs.python.PyResourceBundle
6 | import org.jetbrains.research.deepbugs.python.ide.inspections.base.PyDeepBugsBinExprInspection
7 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
8 |
9 | class PyDeepBugsBinOperandInspection : PyDeepBugsBinExprInspection(0.86f) {
10 | override val model: Perceptron?
11 | get() = CommonModelStorage.common.binOperandModel
12 |
13 | override fun createTooltip(node: PyBinaryExpression, vararg params: String): String =
14 | PyResourceBundle.message(
15 | "deepbugs.python.binary.operand.inspection.warning",
16 | node.leftExpression.text,
17 | node.rightExpression?.text ?: ""
18 | )
19 |
20 | override fun getDisplayName() = PyResourceBundle.message("deepbugs.python.binary.operand.inspection.display")
21 | override fun getShortName(): String = "PyDeepBugsBinOperand"
22 | }
23 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/inspections/PyDeepBugsBinOperatorInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.inspections
2 |
3 | import com.intellij.codeInspection.ProblemDescriptor
4 | import com.jetbrains.python.psi.PyBinaryExpression
5 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
6 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
7 | import org.jetbrains.research.deepbugs.common.ide.quickfixes.ReplaceBinOperatorQuickFix
8 | import org.jetbrains.research.deepbugs.common.ide.quickfixes.ReplaceBinOperatorQuickFix.Companion.toLookups
9 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
10 | import org.jetbrains.research.deepbugs.python.PyDeepBugsConfig
11 | import org.jetbrains.research.deepbugs.python.PyResourceBundle
12 | import org.jetbrains.research.deepbugs.python.extraction.extractOperatorText
13 | import org.jetbrains.research.deepbugs.python.extraction.findOperatorTextRange
14 | import org.jetbrains.research.deepbugs.python.ide.inspections.base.PyDeepBugsBinExprInspection
15 | import org.jetbrains.research.deepbugs.python.ide.quickfixes.PyIgnoreExpressionQuickFix
16 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
17 |
18 | class PyDeepBugsBinOperatorInspection : PyDeepBugsBinExprInspection(0.85f) {
19 | override val model: Perceptron?
20 | get() = CommonModelStorage.common.binOperatorModel
21 |
22 | override fun createProblemDescriptor(node: PyBinaryExpression, data: BinOp, onTheFly: Boolean): ProblemDescriptor {
23 | val textRange = node.findOperatorTextRange()!!
24 | val replaceQuickFix = ReplaceBinOperatorQuickFix(data, textRange, PyDeepBugsConfig.get().quickFixesThreshold,
25 | PyResourceBundle.message("deepbugs.python.replace.operator.family")).takeIf { it.isAvailable() }
26 | return BugDescriptor(
27 | node,
28 | createTooltip(node, *(replaceQuickFix.toLookups())),
29 | onTheFly,
30 | listOfNotNull(PyIgnoreExpressionQuickFix(data, node.text), replaceQuickFix)
31 | )
32 | }
33 |
34 | override fun createTooltip(node: PyBinaryExpression, vararg params: String): String {
35 | val operatorText = node.extractOperatorText() ?: ""
36 | return params.singleOrNull()?.let {
37 | PyResourceBundle.message("deepbugs.python.binary.operator.inspection.warning.single", it, operatorText)
38 | } ?: PyResourceBundle.message("deepbugs.python.binary.operator.inspection.warning", operatorText)
39 | }
40 |
41 | override fun getDisplayName() = PyResourceBundle.message("deepbugs.python.binary.operator.inspection.display")
42 | override fun getShortName(): String = "PyDeepBugsBinOperator"
43 | }
44 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/inspections/PyDeepBugsSwappedArgsInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.inspections
2 |
3 | import com.intellij.codeInspection.ProblemDescriptor
4 | import com.jetbrains.python.psi.PyCallExpression
5 | import org.jetbrains.research.deepbugs.common.datatypes.Call
6 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
7 | import org.jetbrains.research.deepbugs.common.model.CommonModelStorage
8 | import org.jetbrains.research.deepbugs.python.PyResourceBundle
9 | import org.jetbrains.research.deepbugs.python.ide.inspections.base.PyDeepBugsCallExprInspection
10 | import org.jetbrains.research.deepbugs.python.ide.quickfixes.PyFlipFunctionArgumentsQuickFix
11 | import org.jetbrains.research.deepbugs.python.ide.quickfixes.PyIgnoreExpressionQuickFix
12 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
13 |
14 | class PyDeepBugsSwappedArgsInspection : PyDeepBugsCallExprInspection(2, 0.8f) {
15 | override val model: Perceptron?
16 | get() = CommonModelStorage.common.swappedArgsModel
17 |
18 | override fun skip(node: PyCallExpression): Boolean = node.arguments.size != requiredArgsNum
19 |
20 | override fun createProblemDescriptor(node: PyCallExpression, data: Call, onTheFly: Boolean): ProblemDescriptor =
21 | BugDescriptor(node, createTooltip(node), onTheFly, listOf(
22 | PyIgnoreExpressionQuickFix(data, node.text),
23 | PyFlipFunctionArgumentsQuickFix()
24 | ))
25 |
26 | override fun createTooltip(node: PyCallExpression, vararg params: String): String =
27 | PyResourceBundle.message("deepbugs.python.swapped.args.inspection.warning")
28 |
29 | override fun getDisplayName() = PyResourceBundle.message("deepbugs.python.swapped.args.inspection.display")
30 | override fun getShortName(): String = "PyDeepBugsSwappedArgs"
31 | }
32 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/inspections/base/PyDeepBugsBaseInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.inspections.base
2 |
3 | import com.intellij.codeInspection.*
4 | import com.jetbrains.python.inspections.PyInspection
5 | import com.jetbrains.python.inspections.PyInspectionVisitor
6 | import com.jetbrains.python.psi.PyElement
7 | import org.jetbrains.research.deepbugs.common.datatypes.DataType
8 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
9 | import org.jetbrains.research.deepbugs.common.ide.problem.BugDescriptor
10 | import org.jetbrains.research.deepbugs.python.PyDeepBugsConfig
11 | import org.jetbrains.research.deepbugs.python.ide.quickfixes.PyIgnoreExpressionQuickFix
12 | import org.jetbrains.research.keras.runner.nn.model.sequential.Perceptron
13 |
14 | abstract class PyDeepBugsBaseInspection(private val threshold: Float) : PyInspection() {
15 | protected abstract val model: Perceptron?
16 |
17 | protected open fun skip(node: T): Boolean = false
18 |
19 | protected open fun createProblemDescriptor(node: T, data: V, onTheFly: Boolean): ProblemDescriptor =
20 | BugDescriptor(node, createTooltip(node), onTheFly, listOf(PyIgnoreExpressionQuickFix(data, node.text)))
21 |
22 | protected abstract fun createTooltip(node: T, vararg params: String): String
23 |
24 | abstract inner class PyDeepBugsVisitor(
25 | holder: ProblemsHolder,
26 | session: LocalInspectionToolSession
27 | ) : PyInspectionVisitor(holder, session) {
28 | protected fun visit(node: T, collect: T.() -> V?) {
29 | if (skip(node)) return
30 | val data = node.collect() ?: return
31 | val vectorized = data.vectorize()
32 | DeepBugsCounterCollector.tokensMatched(holder?.project ?: return, shortName, matched = vectorized == null)
33 | val result = model?.predict(vectorized ?: return) ?: return
34 | analyzeInspected(result, node, data)
35 | }
36 |
37 | private fun analyzeInspected(result: Float, node: T, data: V) {
38 | if (!PyDeepBugsConfig.isProblem(result, threshold, data)) return
39 | holder?.registerProblem(createProblemDescriptor(node, data, holder!!.isOnTheFly))
40 | DeepBugsCounterCollector.problemFound(holder?.project ?: return, shortName, result)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/inspections/base/PyDeepBugsBinExprInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.inspections.base
2 |
3 | import com.intellij.codeInspection.LocalInspectionToolSession
4 | import com.intellij.codeInspection.ProblemsHolder
5 | import com.jetbrains.python.psi.PyBinaryExpression
6 | import org.jetbrains.research.deepbugs.common.datatypes.BinOp
7 | import org.jetbrains.research.deepbugs.python.datatypes.collect
8 |
9 | abstract class PyDeepBugsBinExprInspection(threshold: Float) : PyDeepBugsBaseInspection(threshold) {
10 | override fun buildVisitor(
11 | holder: ProblemsHolder,
12 | isOnTheFly: Boolean,
13 | session: LocalInspectionToolSession
14 | ) = PyDeepBugsBinOpVisitor(holder, session)
15 |
16 | inner class PyDeepBugsBinOpVisitor(holder: ProblemsHolder, session: LocalInspectionToolSession) : PyDeepBugsVisitor(holder, session) {
17 | override fun visitPyBinaryExpression(node: PyBinaryExpression?) {
18 | visit(node ?: return) { node.collect() }
19 | super.visitPyBinaryExpression(node)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/inspections/base/PyDeepBugsCallExprInspection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.inspections.base
2 |
3 | import com.intellij.codeInspection.LocalInspectionToolSession
4 | import com.intellij.codeInspection.ProblemsHolder
5 | import com.intellij.psi.PsiElementVisitor
6 | import com.jetbrains.python.psi.PyCallExpression
7 | import org.jetbrains.research.deepbugs.common.datatypes.Call
8 | import org.jetbrains.research.deepbugs.python.datatypes.collect
9 |
10 | abstract class PyDeepBugsCallExprInspection(
11 | protected val requiredArgsNum: Int, threshold: Float
12 | ) : PyDeepBugsBaseInspection(threshold) {
13 | override fun buildVisitor(
14 | holder: ProblemsHolder,
15 | isOnTheFly: Boolean,
16 | session: LocalInspectionToolSession
17 | ): PsiElementVisitor = PyDeepBugsCallVisitor(holder, session)
18 |
19 | inner class PyDeepBugsCallVisitor(
20 | holder: ProblemsHolder,
21 | session: LocalInspectionToolSession
22 | ) : PyDeepBugsVisitor(holder, session) {
23 | override fun visitPyCallExpression(node: PyCallExpression?) {
24 | visit(node ?: return) { node.collect() }
25 | super.visitPyCallExpression(node)
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/quickfixes/PyFlipFunctionArgumentsQuickFix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.quickfixes
2 |
3 | import com.intellij.psi.PsiElement
4 | import com.jetbrains.python.psi.PyCallExpression
5 | import org.jetbrains.research.deepbugs.common.ide.quickfixes.FlipFunctionArgumentsQuickFix
6 | import org.jetbrains.research.deepbugs.python.PyResourceBundle
7 |
8 | class PyFlipFunctionArgumentsQuickFix : FlipFunctionArgumentsQuickFix() {
9 | override fun getFamilyName(): String = PyResourceBundle.message("deepbugs.python.flip.args.family")
10 |
11 | override fun PyCallExpression.toArguments(): Pair = Pair(arguments[0], arguments[1])
12 | }
13 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/quickfixes/PyIgnoreExpressionQuickFix.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.quickfixes
2 |
3 | import com.intellij.codeInsight.intention.PriorityAction
4 | import com.intellij.codeInspection.LocalQuickFix
5 | import com.intellij.codeInspection.ProblemDescriptor
6 | import com.intellij.icons.AllIcons
7 | import com.intellij.openapi.command.undo.BasicUndoableAction
8 | import com.intellij.openapi.command.undo.UndoManager
9 | import com.intellij.openapi.project.Project
10 | import com.intellij.openapi.util.Iconable
11 | import org.jetbrains.research.deepbugs.common.datatypes.DataType
12 | import org.jetbrains.research.deepbugs.common.ide.fus.collectors.counter.DeepBugsCounterCollector
13 | import org.jetbrains.research.deepbugs.python.PyDeepBugsConfig
14 | import org.jetbrains.research.deepbugs.python.PyResourceBundle
15 | import javax.swing.Icon
16 |
17 | class PyIgnoreExpressionQuickFix(private val expr: DataType, private val displayText: String) : LocalQuickFix, Iconable, PriorityAction {
18 | override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
19 | val ignore = object : BasicUndoableAction(descriptor.psiElement?.containingFile?.virtualFile) {
20 | override fun redo() = PyDeepBugsConfig.ignoreExpression(expr)
21 | override fun undo() = PyDeepBugsConfig.considerExpression(expr)
22 | }
23 | ignore.redo()
24 | DeepBugsCounterCollector.checkDisabled(project, PyDeepBugsConfig.get().userDisabledChecks.size)
25 | UndoManager.getInstance(project).undoableActionPerformed(ignore)
26 | }
27 |
28 | override fun getIcon(flags: Int): Icon = AllIcons.Actions.Cancel
29 | override fun getPriority(): PriorityAction.Priority = PriorityAction.Priority.LOW
30 |
31 | override fun getFamilyName(): String = PyResourceBundle.message("deepbugs.python.ignore.family")
32 | override fun getName(): String = PyResourceBundle.message("deepbugs.python.ignore.quickfix", displayText)
33 | }
34 |
--------------------------------------------------------------------------------
/py-plugin/src/main/kotlin/org/jetbrains/research/deepbugs/python/ide/ui/PyDeepBugsConfigurable.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python.ide.ui
2 |
3 | import com.intellij.openapi.components.service
4 | import org.jetbrains.research.deepbugs.common.DeepBugsConfig
5 | import org.jetbrains.research.deepbugs.common.ide.ui.DeepBugsConfigurable
6 | import org.jetbrains.research.deepbugs.python.PyDeepBugsConfig
7 | import org.jetbrains.research.deepbugs.python.PyResourceBundle
8 |
9 | class PyDeepBugsConfigurable : DeepBugsConfigurable(
10 | PyDeepBugsConfig.default,
11 | "PyPluginConfig",
12 | PyResourceBundle.message("deepbugs.python.display")
13 | ) {
14 | override fun getSettings(): DeepBugsConfig = service()
15 | }
16 |
--------------------------------------------------------------------------------
/py-plugin/src/main/models/common/binOperandDetectionModel.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/common/binOperandDetectionModel.h5
--------------------------------------------------------------------------------
/py-plugin/src/main/models/common/binOperatorDetectionModel.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/common/binOperatorDetectionModel.h5
--------------------------------------------------------------------------------
/py-plugin/src/main/models/common/swappedArgsDetectionModel.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/common/swappedArgsDetectionModel.h5
--------------------------------------------------------------------------------
/py-plugin/src/main/models/nodeTypeToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/nodeTypeToVector.cbor
--------------------------------------------------------------------------------
/py-plugin/src/main/models/operatorToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/operatorToVector.cbor
--------------------------------------------------------------------------------
/py-plugin/src/main/models/tokenToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/tokenToVector.cbor
--------------------------------------------------------------------------------
/py-plugin/src/main/models/typeToVector.cbor:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains-Research/DeepBugsPlugin/8e9b2c0b070baef9bdcbf9159c0fec0ef357b7a7/py-plugin/src/main/models/typeToVector.cbor
--------------------------------------------------------------------------------
/py-plugin/src/main/resources/DeepBugsPythonBundle.properties:
--------------------------------------------------------------------------------
1 | deepbugs.python.binary.operator.inspection.display=DeepBugs for Python: Possibly incorrect operator
2 | deepbugs.python.binary.operand.inspection.display=DeepBugs for Python: Possibly incorrect operand
3 | deepbugs.python.swapped.args.inspection.display=DeepBugs for Python: Possibly wrong order of function arguments
4 | deepbugs.python.binary.operator.inspection.warning=Possibly incorrect operator: “{0}”
5 | deepbugs.python.binary.operator.inspection.warning.single=Probably you meant “{0}” instead of “{1}”
6 | deepbugs.python.binary.operand.inspection.warning=Possibly incorrect operand: “{0}” or “{1}”
7 | deepbugs.python.swapped.args.inspection.warning=Possibly wrong order of function arguments
8 | deepbugs.python.ignore.family=DeepBugs for Python: Ignore expression
9 | deepbugs.python.flip.args.family=DeepBugs for Python: Fix order of arguments
10 | deepbugs.python.replace.operator.family=DeepBugs for Python: Replace operator
11 | deepbugs.python.display=DeepBugs for Python
12 | deepbugs.python.ignore.quickfix=Always ignore “{0}”
13 | deepbugs.python.group.name=Probable bugs
14 |
--------------------------------------------------------------------------------
/py-plugin/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | DeepBugs for Python
3 | DeepBugsPython
4 | JetBrains
5 | Finds potential bugs and code quality issues for Python using deep learning models.
7 |
8 | Detects several types of bugs, including incorrect function arguments, incorrect comparison, and others, based on extracted code semantics.
9 |
10 | Deep learning models are inspired by DeepBugs.
11 |
12 | To configure, open Preferences/Settings | Tools | DeepBugs for Python .
13 | ]]>
14 |
15 | 0.5
17 | Update for 201.* builds
18 |
19 | 0.4
20 |
21 | Minor bug fixes
22 |
23 |
24 | 0.3
25 |
26 | Significantly reduce plugin size
27 | Add several quick-fixes for detected bugs
28 | Fully rework settings UI and inspections tooltips
29 | A lot of bug fixes and stability improvements
30 |
31 |
32 | 0.2
33 |
34 | Minor improvements
35 |
36 | ]]>
37 |
38 |
39 | com.intellij.modules.lang
40 | com.intellij.modules.python
41 |
42 |
43 |
44 |
45 |
50 |
51 |
56 |
57 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/py-plugin/src/main/resources/META-INF/pluginIcon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/py-plugin/src/main/resources/inspectionDescriptions/PyDeepBugsBinOperand.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of binary operands (arguments of binary operations)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/py-plugin/src/main/resources/inspectionDescriptions/PyDeepBugsBinOperator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of binary operators
4 |
5 |
6 |
--------------------------------------------------------------------------------
/py-plugin/src/main/resources/inspectionDescriptions/PyDeepBugsSwappedArgs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | The inspection detects misuse of function arguments (specifically, their order)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/py-plugin/src/test/kotlin/org/jetbrains/research/deepbugs/python/DeepBugsTestBase.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python
2 |
3 | import com.intellij.testFramework.fixtures.BasePlatformTestCase
4 | import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
5 | import org.jetbrains.research.deepbugs.common.DeepBugsPlugin
6 | import org.jetbrains.research.deepbugs.python.ide.inspections.*
7 | import java.io.File
8 |
9 | abstract class DeepBugsTestBase : BasePlatformTestCase() {
10 | init {
11 | DeepBugsPlugin.setTestPlugin("DeepBugsPython")
12 | }
13 |
14 | override fun getTestDataPath(): String {
15 | return File("src/test/testData").canonicalPath
16 | }
17 |
18 | override fun setUp() {
19 | super.setUp()
20 | myFixture.enableInspections(*inspectionTools)
21 | (myFixture as? CodeInsightTestFixtureImpl)?.canChangeDocumentDuringHighlighting(true)
22 | }
23 |
24 | protected open fun runHighlightTestForFile(file: String) {
25 | myFixture.configureByFile(file)
26 | myFixture.checkHighlighting(true, false, false)
27 | }
28 |
29 | companion object {
30 | val inspectionTools by lazy {
31 | arrayOf(
32 | PyDeepBugsBinOperandInspection(),
33 | PyDeepBugsBinOperatorInspection(),
34 | PyDeepBugsSwappedArgsInspection()
35 | )
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/py-plugin/src/test/kotlin/org/jetbrains/research/deepbugs/python/PyDeepBugsTest.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.research.deepbugs.python
2 |
3 | class PyDeepBugsTest : DeepBugsTestBase() {
4 | fun `test bin operand`() {
5 | runHighlightTestForFile("testIncorrectBinOperandPy.py")
6 | }
7 |
8 | fun `test bin operator`() {
9 | runHighlightTestForFile("testIncorrectBinOperatorPy.py")
10 | }
11 |
12 | fun `test swapped arguments`() {
13 | runHighlightTestForFile("testSwappedArgumentsPy.py")
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/py-plugin/src/test/testData/testIncorrectBinOperandPy.py:
--------------------------------------------------------------------------------
1 | a = 1 + 6
2 | b = 1 / 0
3 |
--------------------------------------------------------------------------------
/py-plugin/src/test/testData/testIncorrectBinOperatorPy.py:
--------------------------------------------------------------------------------
1 | text = "123"
2 | string = "456"
3 |
4 | text / string
5 | text + string
6 |
--------------------------------------------------------------------------------
/py-plugin/src/test/testData/testSwappedArgumentsPy.py:
--------------------------------------------------------------------------------
1 | def size(xx, yy):
2 | return xx, yy
3 |
4 | size(width, height)
5 | size(height, width)
6 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "deep-bugs"
2 |
3 | include(":common")
4 | include(":py-plugin")
5 | include(":js-plugin")
6 | include(":keras-runner")
7 |
--------------------------------------------------------------------------------