Skip to content

Commit

Permalink
Merge #4667
Browse files Browse the repository at this point in the history
4667: GRAM: fix type path parsing r=vlad20012 a=Undin

After rust-lang/rust#43540 disambiguator `::` is allowed in "type" paths.
But our grammar forbade it previously because it had been written before the corresponding changes in rustc.

These changes fix the grammar. Also, they highlight redundant `::` in type paths and provide fix to remove it
![2019-11-21 11 25 22](https://user-images.githubusercontent.com/2539310/69320139-a5193b80-0c51-11ea-85ba-2ddfe0a41fcb.gif)
Fixes #4430



Co-authored-by: Arseniy Pendryak <a.pendryak@yandex.ru>
  • Loading branch information
bors[bot] and Undin authored Nov 22, 2019
2 parents 57f953a + a6db191 commit 895e6a2
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 115 deletions.
50 changes: 25 additions & 25 deletions src/main/grammars/RustParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ File ::= [ SHEBANG_LINE ] InnerAttr* Items
ExprCodeFragment ::= Expr?
StmtCodeFragment ::= Stmt?
TypeRefCodeFragment ::= TypeReference?
PathWithColonsCodeFragment ::= PathGenericArgsWithColons?
PathWithoutColonsCodeFragment ::= PathGenericArgsWithoutColons?
ValuePathCodeFragment ::= ValuePathGenericArgs?
TypePathCodeFragment ::= TypePathGenericArgs?

///////////////////////////////////////////////////////////////////////////////////////////////////
// Attributes
Expand Down Expand Up @@ -194,20 +194,20 @@ TypeQual ::= '<' TypeReference [ as TraitRef] '>' '::' {

left PathSegment ::= '::' PathIdent PathTypeArguments? { elementType = Path }

private PathTypeArguments ::= <<isPathMode 'COLONS'>> ColonTypeArgumentList
| <<isPathMode 'NO_COLONS '>> ( TypeArgumentList | PathParameters RetType? ) // Fn(i32) -> i32 sugar
private PathTypeArguments ::= <<isPathMode 'VALUE'>> ColonTypeArgumentList
| <<isPathMode 'TYPE'>> ( TypeArgumentList | PathParameters RetType? ) // Fn(i32) -> i32 sugar

TypeArgumentList ::= TypeArgumentListImpl {
extends = "org.rust.lang.core.psi.ext.RsStubbedElementImpl<?>"
stubClass = "org.rust.lang.core.stubs.RsPlaceholderStub"
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
}
ColonTypeArgumentList ::= '::' TypeArgumentListImpl { elementType = TypeArgumentList }
ColonTypeArgumentList ::= &'::' TypeArgumentListImpl { elementType = TypeArgumentList }

private TypeArgumentListImpl ::= '<' !'=' ( <<list_element Lifetime>>*
<<list_element (!(identifier ('='|':')) !'>' TypeReference)>>*
<<list_element (!'>' (BlockExpr | LitExpr | &('-' LitExpr) UnaryExpr))>>*
<<list_element AssocTypeBinding>>*) '>' { pin = 2 }
private TypeArgumentListImpl ::= '::'? '<' !'=' ( <<list_element Lifetime>>*
<<list_element (!(identifier ('='|':')) !'>' TypeReference)>>*
<<list_element (!'>' (BlockExpr | LitExpr | &('-' LitExpr) UnaryExpr))>>*
<<list_element AssocTypeBinding>>*) '>' { pin = 3 }
AssocTypeBinding ::= identifier (AssocTypeBindingType | AssocTypeBindingBound) {
implements = [ "org.rust.lang.core.psi.ext.RsNameIdentifierOwner"
"org.rust.lang.core.psi.ext.RsReferenceElement" ]
Expand All @@ -225,20 +225,20 @@ private AssocTypeBindingBound ::= ':' TypeBounds { pin = 1 }
// a::b<T,U>::c<V,W>
// std::Fn(V) -> W
// std::Fn(V)
PathGenericArgsWithoutColons ::= <<typeQuals 'ON' <<pathMode 'NO_COLONS' PathImpl>>>> { elementType = Path }
PathGenericArgsWithoutColonsNoTypeQual ::= <<typeQuals 'OFF' <<pathMode 'NO_COLONS' PathImpl>>>> { elementType = Path }
TypePathGenericArgs ::= <<typeQuals 'ON' <<pathMode 'TYPE' PathImpl>>>> { elementType = Path }
TypePathGenericArgsNoTypeQual ::= <<typeQuals 'OFF' <<pathMode 'TYPE' PathImpl>>>> { elementType = Path }

// Paths without type arguments, for use declarations:
// a::b::c
PathWithoutTypes ::= <<typeQuals 'OFF' <<pathMode 'NO_TYPES' PathImpl>>>> { elementType = Path }
PathWithoutTypeArgs ::= <<typeQuals 'OFF' <<pathMode 'NO_TYPE_ARGS' PathImpl>>>> { elementType = Path }

// Paths for expressions:
// a::b::<T,U>::c
PathGenericArgsWithColons ::= <<typeQuals 'ON' <<pathMode 'COLONS' PathImpl>>>> { elementType = Path }
PathGenericArgsWithColonsNoTypeQual ::= <<typeQuals 'OFF' <<pathMode 'COLONS' PathImpl>>>> { elementType = Path }
ValuePathGenericArgs ::= <<typeQuals 'ON' <<pathMode 'VALUE' PathImpl>>>> { elementType = Path }
ValuePathGenericArgsNoTypeQual ::= <<typeQuals 'OFF' <<pathMode 'VALUE' PathImpl>>>> { elementType = Path }

// Path semantically constrained to resolve to a trait
TraitRef ::= PathGenericArgsWithoutColonsNoTypeQual {
TraitRef ::= TypePathGenericArgsNoTypeQual {
extends = "org.rust.lang.core.psi.ext.RsStubbedElementImpl<?>"
stubClass = "org.rust.lang.core.stubs.RsPlaceholderStub"
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
Expand All @@ -253,7 +253,7 @@ Vis ::= crate | pub VisRestriction? {
stubClass = "org.rust.lang.core.stubs.RsVisStub"
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
}
VisRestriction ::= '(' in? PathWithoutTypes ')' {
VisRestriction ::= '(' in? PathWithoutTypeArgs ')' {
extends = "org.rust.lang.core.psi.ext.RsStubbedElementImpl<?>"
stubClass = "org.rust.lang.core.stubs.RsPlaceholderStub"
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
Expand Down Expand Up @@ -349,7 +349,7 @@ FnParameters ::= '(' !',' [ SelfParameter (',' | &')') ]
LambdaParameters ::= '|' !',' [ <<comma_separated_list LambdaParameter>> ] '|'

FnTypeParameters ::= <<variadic_params_impl AnonParameter>>
PathParameters ::= '(' [ <<comma_separated_list PathParameter>> ] ')' { pin = 1 }
PathParameters ::= '::'? '(' [ <<comma_separated_list PathParameter>> ] ')' { pin = 2 }


private meta variadic_params_impl ::= '(' [ <<param>> (',' <<param>>)* [ ',' '...'? ] ] ')' { pin = 1 }
Expand Down Expand Up @@ -496,8 +496,8 @@ PatBox ::= box Pat
// }
PatIdent ::= PatBinding [ '@' Pat ]

PatStruct ::= PathGenericArgsWithColonsNoTypeQual '{' PatField_with_recover* '..'? '}'
PatTupleStruct ::= PathGenericArgsWithColonsNoTypeQual '(' SeqPat ')'
PatStruct ::= ValuePathGenericArgsNoTypeQual '{' PatField_with_recover* '..'? '}'
PatTupleStruct ::= ValuePathGenericArgsNoTypeQual '(' SeqPat ')'

// TODO: actual recover
private Pat_with_recover ::= Pat (',' | &(')' | ']' | '..'))
Expand Down Expand Up @@ -561,7 +561,7 @@ UseItem ::= AttrsAndVis use UseSpeck ';' {
// foo::bar::{self, foo};
// foo::{};
// ::foo::*;
UseSpeck ::= PathWithoutTypes [ Alias | '::' UseSpeckProjection ]
UseSpeck ::= PathWithoutTypeArgs [ Alias | '::' UseSpeckProjection ]
| '::'? UseSpeckProjection {
extends = "org.rust.lang.core.psi.ext.RsUseSpeckImplMixin"
stubClass = "org.rust.lang.core.stubs.RsUseSpeckStub"
Expand Down Expand Up @@ -808,7 +808,7 @@ private TypeReferenceInner ::= ArrayType
| ExplicitTraitType
| TrivialBaseType
// External rule to find the difference between `T` and `T+T`
| <<baseOrTraitType PathGenericArgsWithoutColons ImplicitTraitType TraitType_upper>>
| <<baseOrTraitType TypePathGenericArgs ImplicitTraitType TraitType_upper>>
| MacroType
| ForInType // FIXME O(2^n) for types like `for<'a> A<for<'b> B<for<'c> C<...>>>`

Expand Down Expand Up @@ -889,7 +889,7 @@ ForInType ::= ForLifetimes (FnPointerType | TraitRef) {
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
}

BaseType ::= TrivialBaseTypeInner | PathGenericArgsWithoutColons {
BaseType ::= TrivialBaseTypeInner | TypePathGenericArgs {
implements = "org.rust.lang.core.psi.ext.RsTypeElement"
extends = "org.rust.lang.core.psi.ext.RsStubbedElementImpl<?>"
stubClass = "org.rust.lang.core.stubs.RsBaseTypeStub"
Expand Down Expand Up @@ -1070,7 +1070,7 @@ LambdaExpr ::= OuterAttr* [asyncBlock | static] move? LambdaParameters RetType?
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
}

StructLiteral ::= <<checkStructAllowed>> OuterAttr* PathGenericArgsWithColonsNoTypeQual StructLiteralBody {
StructLiteral ::= <<checkStructAllowed>> OuterAttr* ValuePathGenericArgsNoTypeQual StructLiteralBody {
implements = [ "org.rust.lang.core.psi.ext.RsOuterAttributeOwner" ]
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
}
Expand All @@ -1092,7 +1092,7 @@ private StructLiteralField_with_recover ::= StructLiteralField (',' | &'}') {

private StructLiteralField_recover ::= !(identifier | INTEGER_LITERAL | ',' | '}' | '..' | '#')

PathExpr ::= OuterAttr* PathGenericArgsWithColons {
PathExpr ::= OuterAttr* ValuePathGenericArgs {
implements = [ "org.rust.lang.core.psi.ext.RsOuterAttributeOwner" ]
elementTypeFactory = "org.rust.lang.core.stubs.StubImplementationsKt.factory"
}
Expand Down Expand Up @@ -1318,7 +1318,7 @@ Macro2 ::= AttrsAndVis MACRO_KW identifier ( Macro2FunctionLikeBody | Macro2Matc
private Macro2FunctionLikeBody ::= '(' MacroPatternContents ')' '{' MacroExpansionContents '}'
private Macro2MatchLikeBody ::= '{' (MacroCase ','?)* '}'

fake MacroCall ::= AttrsAndVis PathWithoutTypes '!' identifier? (
fake MacroCall ::= AttrsAndVis PathWithoutTypeArgs '!' identifier? (
MacroArgument | ExprMacroArgument | FormatMacroArgument | AssertMacroArgument |
VecMacroArgument | LogMacroArgument | IncludeMacroArgument | ConcatMacroArgument | EnvMacroArgument
) ';'? {
Expand Down
29 changes: 25 additions & 4 deletions src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@
package org.rust.ide.annotator

import com.intellij.codeInsight.daemon.impl.HighlightRangeExtension
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.ide.annotator.AnnotatorBase
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.AnnotationSession
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
import org.rust.cargo.project.workspace.CargoWorkspace.Edition
import org.rust.cargo.project.workspace.PackageOrigin
import org.rust.ide.annotator.fixes.AddModuleFileFix
import org.rust.ide.annotator.fixes.AddTurbofishFix
import org.rust.ide.annotator.fixes.CreateLifetimeParameterFromUsageFix
import org.rust.ide.annotator.fixes.MakePublicFix
import org.rust.ide.annotator.fixes.*
import org.rust.ide.refactoring.RsNamesValidator.Companion.RESERVED_LIFETIME_NAMES
import org.rust.ide.utils.isCfgUnknown
import org.rust.ide.utils.isEnabledByCfg
Expand Down Expand Up @@ -47,6 +46,8 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
override fun visitBaseType(o: RsBaseType) = checkBaseType(holder, o)
override fun visitCondition(o: RsCondition) = checkCondition(holder, o)
override fun visitConstant(o: RsConstant) = checkConstant(holder, o)
override fun visitTypeArgumentList(o: RsTypeArgumentList) = checkTypeArgumentList(holder, o)
override fun visitValueParameterList(o: RsValueParameterList) = checkValueParameterList(holder, o)
override fun visitValueArgumentList(o: RsValueArgumentList) = checkValueArgumentList(holder, o)
override fun visitStructItem(o: RsStructItem) = checkDuplicates(holder, o)
override fun visitEnumItem(o: RsEnumItem) = checkEnumItem(holder, o)
Expand Down Expand Up @@ -563,6 +564,26 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
}
}

private fun checkTypeArgumentList(holder: RsAnnotationHolder, args: RsTypeArgumentList) {
checkRedundantColonColon(holder, args)
}

private fun checkValueParameterList(holder: RsAnnotationHolder, args: RsValueParameterList) {
checkRedundantColonColon(holder, args)
}

private fun checkRedundantColonColon(holder: RsAnnotationHolder, args: RsElement) {
// For some reason `::(i32) -> i32` in `Fn::(i32) -> i32` has `RsValueParameterList` instead of `RsTypeArgumentList`.
// `RsValueParameterList` and `RsTypeArgumentList` shouldn't have common interfaces
// So we have to use low level ASTNode API to avoid code duplication
val coloncolon = args.node.findChildByType(RsElementTypes.COLONCOLON)?.psi ?: return
// `::` is redundant only in types
if (PsiTreeUtil.getParentOfType(args, RsTypeReference::class.java, RsTraitRef::class.java) == null) return
val annotation = holder.createWeakWarningAnnotation(coloncolon, "Redundant `::`") ?: return
annotation.highlightType = ProblemHighlightType.LIKE_UNUSED_SYMBOL
annotation.registerFix(RemoveElementFix(coloncolon))
}

private fun checkValueArgumentList(holder: RsAnnotationHolder, args: RsValueArgumentList) {
val (expectedCount, variadic) = when (val parent = args.parent) {
is RsCallExpr -> parent.expectedParamsCount()
Expand Down
20 changes: 1 addition & 19 deletions src/main/kotlin/org/rust/ide/annotator/fixes/RemoveAttrFix.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,7 @@

package org.rust.ide.annotator.fixes

import com.intellij.codeInspection.LocalQuickFixOnPsiElement
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.rust.lang.core.psi.ext.RsAttr
import org.rust.lang.core.psi.ext.name

class RemoveAttrFix(attr: RsAttr) : LocalQuickFixOnPsiElement(attr) {
private val _text = run {
val suffix = attr.metaItem.name?.let { " `$it`" } ?: ""

"Remove attribute$suffix"
}

override fun getText() = _text
override fun getFamilyName() = "Remove attribute"

override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) {
val attr = startElement as? RsAttr ?: return
attr.delete()
}
}
class RemoveAttrFix(attr: RsAttr) : RemoveElementFix(attr, "attribute" + (attr.metaItem.name?.let { " `$it`" } ?: ""))
23 changes: 23 additions & 0 deletions src/main/kotlin/org/rust/ide/annotator/fixes/RemoveElementFix.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.ide.annotator.fixes

import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile

open class RemoveElementFix(
element: PsiElement,
private val removingElementName: String = "`${element.text}`"
) : LocalQuickFixAndIntentionActionOnPsiElement(element) {
override fun getFamilyName(): String = "Remove"
override fun getText(): String = "Remove $removingElementName"
override fun invoke(project: Project, file: PsiFile, editor: Editor?, startElement: PsiElement, endElement: PsiElement) {
startElement.delete()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ data class ImportContext private constructor(
mod = element.containingMod,
superMods = LinkedHashSet(element.containingMod.superMods),
scope = RsWithMacrosScope(project, GlobalSearchScope.allScope(project)),
pathParsingMode = PathParsingMode.NO_COLONS,
pathParsingMode = PathParsingMode.TYPE,
attributes = element.stdlibAttributes,
namespaceFilter = { true }
)
Expand All @@ -689,8 +689,8 @@ private val RsPath.pathParsingMode: PathParsingMode
is RsPathExpr,
is RsStructLiteral,
is RsPatStruct,
is RsPatTupleStruct -> PathParsingMode.COLONS
else -> PathParsingMode.NO_COLONS
is RsPatTupleStruct -> PathParsingMode.VALUE
else -> PathParsingMode.TYPE
}
private val RsElement.stdlibAttributes: RsFile.Attributes
get() = (crateRoot?.containingFile as? RsFile)?.attributes ?: RsFile.Attributes.NONE
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/rust/lang/core/macros/FragmentKind.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ enum class FragmentKind(private val kind: String) {
.enter_section_(adaptBuilder, 0, 0, null)

val parsed = when (this) {
Path -> RustParser.PathGenericArgsWithColons(adaptBuilder, 0)
Path -> RustParser.ValuePathGenericArgs(adaptBuilder, 0)
Expr -> RustParser.Expr(adaptBuilder, 0, -1)
Ty -> RustParser.TypeReference(adaptBuilder, 0)
Pat -> RustParser.Pat(adaptBuilder, 0)
Expand Down
43 changes: 26 additions & 17 deletions src/main/kotlin/org/rust/lang/core/parser/RustParserUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,21 @@ import org.rust.stdext.removeLast
@Suppress("UNUSED_PARAMETER")
object RustParserUtil : GeneratedParserUtilBase() {
enum class PathParsingMode {
/** `Foo::<i32>` */
COLONS,
/** `Foo<i32>` */
NO_COLONS,
/** `Foo` */
NO_TYPES
/**
* Accepts paths like `Foo::<i32>`
* Should be used to parse references to values
*/
VALUE,
/**
* Accepts paths like `Foo<i32>`, `Foo::<i32>`, Fn(i32) -> i32 and Fn::(i32) -> i32
* Should be used to parse type and trait references
*/
TYPE,
/**
* Accepts paths like `Foo`
* Should be used to parse paths where type args cannot be specified: `use` items, macro calls, etc.
*/
NO_TYPE_ARGS
}
enum class BinaryMode { ON, OFF }
enum class MacroCallParsingMode(val semicolon: Boolean, val pin: Boolean, val forbidExprSpecialMacros: Boolean) {
Expand Down Expand Up @@ -61,22 +70,22 @@ object RustParserUtil : GeneratedParserUtilBase() {
private val TYPE_QUAL_ALLOWED: Int = makeBitMask(2)
private val STMT_EXPR_MODE: Int = makeBitMask(3)

private val PATH_COLONS: Int = makeBitMask(4)
private val PATH_NO_COLONS: Int = makeBitMask(5)
private val PATH_NO_TYPES: Int = makeBitMask(6)
private val PATH_VALUE: Int = makeBitMask(4)
private val PATH_TYPE: Int = makeBitMask(5)
private val PATH_NO_TYPE_ARGS: Int = makeBitMask(6)
private fun setPathMod(flags: Int, mode: PathParsingMode): Int {
val flag = when (mode) {
PathParsingMode.COLONS -> PATH_COLONS
PathParsingMode.NO_COLONS -> PATH_NO_COLONS
PathParsingMode.NO_TYPES -> PATH_NO_TYPES
PathParsingMode.VALUE -> PATH_VALUE
PathParsingMode.TYPE -> PATH_TYPE
PathParsingMode.NO_TYPE_ARGS -> PATH_NO_TYPE_ARGS
}
return flags and (PATH_COLONS or PATH_NO_COLONS or PATH_NO_TYPES).inv() or flag
return flags and (PATH_VALUE or PATH_TYPE or PATH_NO_TYPE_ARGS).inv() or flag
}

private fun getPathMod(flags: Int): PathParsingMode = when {
BitUtil.isSet(flags, PATH_COLONS) -> PathParsingMode.COLONS
BitUtil.isSet(flags, PATH_NO_COLONS) -> PathParsingMode.NO_COLONS
BitUtil.isSet(flags, PATH_NO_TYPES) -> PathParsingMode.NO_TYPES
BitUtil.isSet(flags, PATH_VALUE) -> PathParsingMode.VALUE
BitUtil.isSet(flags, PATH_TYPE) -> PathParsingMode.TYPE
BitUtil.isSet(flags, PATH_NO_TYPE_ARGS) -> PathParsingMode.NO_TYPE_ARGS
else -> error("Path parsing mode not set")
}

Expand Down Expand Up @@ -313,7 +322,7 @@ object RustParserUtil : GeneratedParserUtilBase() {
val macroName = lookupSimpleMacroName(b)
if (mode.forbidExprSpecialMacros && macroName in SPECIAL_EXPR_MACROS) return false

if (!RustParser.PathWithoutTypes(b, level + 1) || !consumeToken(b, EXCL)) {
if (!RustParser.PathWithoutTypeArgs(b, level + 1) || !consumeToken(b, EXCL)) {
return false
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/org/rust/lang/core/psi/RsCodeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.LightVirtualFile
import org.rust.lang.RsFileType
import org.rust.lang.RsLanguage
import org.rust.lang.core.parser.RustParserUtil
import org.rust.lang.core.parser.RustParserUtil.PathParsingMode
import org.rust.lang.core.parser.RustParserUtil.PathParsingMode.*
import org.rust.lang.core.psi.ext.RsElement
import org.rust.lang.core.psi.ext.RsInferenceContextOwner
import org.rust.lang.core.psi.ext.RsMod
Expand Down Expand Up @@ -149,9 +149,9 @@ class RsPathCodeFragment(
companion object {
@JvmStatic
private fun PathParsingMode.elementType() = when (this) {
PathParsingMode.NO_COLONS -> RsCodeFragmentElementType.PATH_WITHOUT_COLONS
PathParsingMode.COLONS -> RsCodeFragmentElementType.PATH_WITH_COLONS
PathParsingMode.NO_TYPES -> error("NO_TYPES mode is not supported; use NO_COLONS")
TYPE -> RsCodeFragmentElementType.TYPE_PATH_CODE_FRAGMENT
VALUE -> RsCodeFragmentElementType.VALUE_PATH_CODE_FRAGMENT
NO_TYPE_ARGS -> error("$NO_TYPE_ARGS mode is not supported; use $TYPE")
}
}
}
Loading

0 comments on commit 895e6a2

Please sign in to comment.