Hay algunas situaciones en las que nos gustaría aplicar condicionalmente una verificación de pelusa en función de si el código que se está aplicando es código de prueba o no. Por ejemplo, nos gustaría prohibir "cualquiera" del código de producción, ya que no es seguro. Pero en las pruebas, 'any' puede ser útil para proporcionar implementaciones falsas o simuladas de servicios, o para transmitir a través de él para que pueda llamar a métodos privados. O podríamos querer prohibir un conjunto diferente de métodos en las pruebas frente al código de producción, por ejemplo.
Lo que propongo es una forma de habilitar condicionalmente las comprobaciones de pelusa basadas en una coincidencia de expresiones regulares en el nombre del archivo. Esto también podría ser útil para desactivar las comprobaciones de pelusa para ciertos directorios (que contienen código "heredado", por ejemplo), o para archivos .tsx o .d.ts, etc.
Aquí hay algunas ideas de sintaxis del hombre de paja; También estoy abierto a sugerencias.
{
"rules": {
"no-any": {"other": true},
"no-console":
{
"test": [true, "warn", "error"],
"other": [true, "log", "warn", "error"]
}
},
"sections": {
"test": ".*\\.spec\\.ts$"
}
}
"Otro" serían cosas que no coinciden con ninguna de las expresiones regulares. Esto es bastante conciso, pero creo que la legibilidad de la sección de reglas sufre un poco.
{
"rules": {
"no-any": true,
"no-console": [true, "log", "warn", "error"]
},
"override": {
"match": ".*\\.spec\\.ts$",
"rules": {
"no-any": false,
"no-console": [true, "warn", "error"]
}
}
}
(esto quizás debería ser una matriz, para permitir también múltiples invalidaciones).
Si coloca sus pruebas y el código de producción en directorios separados, no necesitaría tal característica. Si no proporciona un archivo de configuración como argumento CLI, TSLint usa el tslint.json
más cercano. Por lo tanto, puede tener diferentes configuraciones para diferentes carpetas. Al usar "extends"
, puede usar la misma configuración base y anular solo reglas específicas.
Entiendo que muchos proyectos de Angular y React ponen pruebas en el mismo directorio que el código de producción correspondiente. Personalmente creo que esta es una mala práctica. He visto suficientes personas (accidentalmente) importando símbolos de pruebas en código de producción.
En mi opinión, la característica propuesta agrega mucha complejidad. Puede que la implementación no sea tan difícil, pero hace que el archivo de configuración sea difícil de leer y comprender.
Si vamos a implementar esto, preferiría la segunda sugerencia.
También necesitaríamos discutir cómo funciona al extender configuraciones. ¿En qué orden se aplican las anulaciones?
Es cierto que podría simplemente separar el código, pero daña la ergonomía. O tienes
src/
tslint.json
a/
b/
c/
test/
tslint.json (extends ../src)
a/
b/
c/
y c/foo.spec.ts
tiene que import {symbol} from '../../../a/b/c/foo';
Ese camino se pone feo en nuestro monorepo, donde los archivos suelen estar muy profundos en el árbol.
o tienes
a/
src/
tslint.json
test/
tslint.json (extends ../src)
b/
src/
tslint.json
test/
tslint.json (extends ../src)
c/
src/
tslint.json
test/
tslint.json (extends ../src)
que son demasiados archivos tslint.json
Sobre el tema de las anulaciones: yo diría que las anulaciones se aplican en el mismo orden en que se aplican las reglas. No sé qué es eso, y no pude encontrar documentación, pero intuitivamente creo que sería así:
// a.json
{"rules": {"foo": [true, 1]}}
// b.json
{"rules": {"foo": [true, 2]}}
// c.json
{
"extends": ["a.json", "b.json"],
"rules": {"foo": [true, 3]}
}
daría como resultado que la regla "foo" tenga el argumento 3. Si esa regla no estuviera en c.json
, entonces "foo" debería tener el valor 2, debido al orden de la matriz "amplía".
Para las anulaciones, esperaría que se aplicara el mismo orden. Para mí tiene sentido usar la última anulación que coincida con la expresión regular proporcionada, teniendo en cuenta el orden en el que se consideran las reglas de 'extensión'. Un solo ejemplo de archivo:
{
"rules": {"a": [true, 1]},
"override": [
{"match": "test|spec", "rules": {"a": [true, 2]}},
{"match": "test", "rules": {"a": [true, 3]}}
]
}
tendría el valor 2 para la regla "foo" cuando la ruta del archivo contiene "spec", 3 si contiene "test" y 1 en caso contrario. (obviamente, no es un conjunto de anulaciones muy útil, ya que "prueba" también podría omitirse de la primera, pero entiendes la idea)
¿Tiene sentido y responde a tu pregunta?
@calebegg Hay algunos otros casos
// a.json
{
"rules": {"foo": [true, 1]},
"override": {"match": "test|spec", "rules": {"foo": [true, 2]}}
}
// b.json
{
"extends": "./a.json"
"rules": {"foo": false}
}
¿Cuál es el resultado esperado?
2
porque el pedido es a.json/rules
-> b.json/rules
-> a.json/override
false
porque el pedido es a.json/rules
-> a.json/override
-> b.json/rules
Lo mismo aquí, cuál es el resultado esperado:
// c.json
{
"rules": {"foo": [true, 1]},
"override": {"match": "test|spec", "rules": {"foo": false}}
}
// d.json
{
"extends": "./a.json"
"rules": {"foo": {"options": 2}},
"override": {"match": "test|spec", "rules": {"foo": {"options": 3}}}
}
Solo un pensamiento al azar: ¿Por qué no simplemente hacer coincidir los patrones en orden y anular (parcialmente) la coincidencia anterior?
{
"rules": { // same as "*"
"rule-one": true,
"rule-two": true
},
"*.js?(x)": { // we could get rid of "jsRules" with this
"rule-two": false
},
"*.{t,j}sx": {
"jsx-rule": true
},
"*.spec.*" {
"rule-one": false
}
}
Algunos ejemplos:
foo.ts
: regla-uno, regla-dosfoo.tsx
: regla-uno, regla-dos, regla-jsxfoo.js
: regla-unofoo.jsx
: regla-uno, regla-jsxfoo.spec.tsx
: regla-dos, regla-jsxfoo.spec.js
: ningunoSimplemente no sé dónde poner esto dentro de la configuración. El mismo nivel que "rules"
facilita la escritura, pero puede confundir a los usuarios, porque está al mismo nivel que "extends"
, "rulesDirectory"
, ...
Otro problema es extender configs. Si aplicamos todas las invalidaciones de la configuración base y luego las invalidaciones de la configuración actual, es bastante difícil de entender.
También hace que el código sea más complejo. Actualmente, las configuraciones se combinan durante el análisis. Con esta propuesta, la configuración final solo se conoce cuando tenemos un nombre de archivo.
Hola,
Esta característica será genial. Creo que Eslint admite esta función: https://eslint.org/docs/user-guide/configuring#configuration -based-on-glob-patterns. Entonces, la sintaxis y la semántica podrían ser lo mismo, para evitar confusiones.
@minomikula Muchas gracias. Busqué los documentos de ESLint antes, pero no encontré esta sección.
Su enfoque tiene sentido. Para resumir:
"overrides"
sección "files"
). si uno de ellos coincide, se aplica la configuración"excludedFiles"
Hay algunas cosas a considerar al migrar este comportamiento a TSLint:
extends
y linterOptions
en anulacionesrulesDirectory
rules
y jsRules
en anulaciones o depreciamos jsRules
a favor de una anulación de **/*.js?(x)
?¿Pensamientos o comentarios @adidahiya @calebegg @alexeagle @minomikula?
Oh, vaya, sí, ese enfoque me parece razonable. También debería haber buscado el estado de la técnica.
¡Esta sería una adición increíble! El enfoque eslint funciona muy bien cuando se deshabilitan condicionalmente algunas reglas en archivos de prueba.
@calebegg , ¿todavía planeas impulsar esto cuando encuentres tiempo?
Sí, definitivamente me gustaría trabajar en esto. @ajafff ¿En general, está satisfecho con comenzar con el enfoque de ESLint e iterar en las relaciones públicas? ¿O cree que hay cuestiones de diseño de las que deberíamos hablar primero?
¿Queremos permitir reglas y jsRules en anulaciones o desaprobamos jsRules a favor de una anulación * / .js? (x)?
Para mí tiene sentido desaprobarlo, pero no me siento muy fuerte de ninguna manera.
@calebegg Estoy bien con el enfoque de ESLint. Implementé un concepto muy similar en mi tiempo de ejecución de linter POC https://github.com/fimbullinter/wotan/tree/master/packages/wotan#overrides
La integración en la API de TSLint actual podría ser difícil, porque actualmente fusiona todas las configuraciones durante el análisis. Esto debe posponerse hasta que se conozca el nombre del archivo y se debe hacer para cada archivo.
Este es sin duda un cambio de API importante.
@calebegg @mitchlloyd @ajafff @alexeagle Veo pocos beneficios en esta función sobre simplemente anidar archivos tslint.json
para anular las configuraciones externas. esa característica ya funciona hoy y no requiere interrupciones complejas de API. ¿Se sentiría ofendido si rechazáramos esta solicitud?
El anidamiento no resuelve los problemas discutidos aquí. Muchas personas quieren que sus pruebas en la misma estructura de directorio que el código se pone a prueba, y simplemente no hay buena manera de hacer eso con tslint en este momento.
Hay muchos proyectos que colocan archivos de especificaciones en el mismo directorio que las fuentes. Esto se ha convertido en una práctica recomendada en muchos entornos, Angular CLI genera una estructura de proyecto como esa, etc. No creo que sea realista anidar archivos de configuración tslint vaya a funcionar para todas estas personas.
Estoy de acuerdo en que la estructura de mi proyecto no debería estar dictada por una herramienta de deshilachado. En cambio, la herramienta de pelado debe admitir patrones comunes existentes. Colocar pruebas y archivos fuente es un patrón común.
@giladgray El cambio solicitado admite un escenario en el que los usuarios colocan sus pruebas y archivos de producción uno al lado del otro de esta manera:
some-dir/
my-component.ts
my-component.test.ts
¿Cómo abordaría "anidar archivos tslint.json
" este caso de uso cuando queremos reglas diferentes para my-component.ts
y my-component.test.ts
?
Las pautas angulares de
@ohjames Permanezcamos en el tema y evitemos desviarnos hacia los ataques personales, ¿de acuerdo? Sugerir que alguien no está en condiciones de mantener su propio proyecto no es la forma de influir en el OSS, y ciertamente no ayudará a lo que todos estamos defendiendo aquí.
Tiene sentido querer anulaciones para archivos que no encajan en una estructura anidada como se mencionó anteriormente. Me parece que el comentario de @giladgray tenía la intención de determinar si todavía había un interés significativo de la comunidad en este cambio, dado que no había habido actividad sobre este tema durante más de 6 meses. Esto se evidencia específicamente en su comentario sobre el PR abierto (# 3708):
Si desea continuar con esto, actualice esta rama para que podamos revisarla, o ciérrela si ya no es relevante. cerraremos esto si no tenemos noticias suyas en dos semanas.
@ohjames Te sugiero que reconsideres tu comentario; como mencionó @DanielSchaffer , los ataques personales no te ayudarán aquí ni en ningún otro lugar del software de código abierto. Todos están haciendo todo lo posible para crear un software bueno, confiable y rico en funciones, y atacar a las personas de ninguna manera contribuye a eso.
¿Hay alguna actualización sobre este tema?
La idea propuesta por @ajafff en su comentario resumido parece razonable y satisface toda variedad de necesidades. Usar la misma semántica que eslint es un buen camino a seguir.
Como comenté en el # 1063 relacionado, mi caso de uso sería que el uso de tslint-microsoft-contrib actualmente bombardea los componentes de un solo archivo de Vue para algunas reglas. Esto podría ser un problema de Vue o un problema de TSLint, y esos equipos podrían o no solucionar el problema específico; deshabilitar las reglas infractoras hasta que eso suceda parece una solución simple que no es demasiado engorrosa. En comparación con tener que agregar la misma directiva de deshabilitación a cada archivo .vue y actualizarlo en todos esos lugares a medida que cambia el soporte de la regla. Tampoco tiene sentido dividir un proyecto en archivos .vue y .ts, sería una estructura muy incómoda.
Estoy a favor de que se incorpore esta característica. ¿Quizás también podamos resolver limpiamente la solicitud tslintignore en el n. ° 73 permitiendo que algunas anulaciones deshabiliten por completo todas las reglas?
{
"files": "./src/test-data/*.ts",
"reset": true // Resets tslint.json to {}
}
tslint-microsoft-contrib actualmente bombardea los componentes de un solo archivo de Vue para algunas reglas
Oh, @millimoose, ¿ podrías presentar un problema en tslint-microsoft-contrib?
@JoshuaKGoldberg : ya había hecho un informe detallado de ese error en @ vuejs / vue-cli, que parecía el más apropiado. (Está marcado como "en espera de reproducción", así que supongo que no está tan fuera de lugar). Lo mencioné como un motivador para intervenir aquí. Es el tipo de cosas que pueden surgir y surgirán en un ecosistema en evolución, lo que debería ser un argumento para que las herramientas sean lo suficientemente flexibles como para sortear obstáculos sin tener que escribir trucos en torno a los errores de los demás.
¿Alguna actualización sobre este tema?
Este problema está marcado actualmente como 'Necesita propuesta', pero creo que ya tenemos una propuesta en https://github.com/palantir/tslint/issues/3447#issuecomment -344020834?
La propuesta de @RoystonS @ajafff mencionó algunos cabos sueltos que deberían abordarse:
Hay algunas cosas a considerar al migrar este comportamiento a TSLint:
- definitivamente deberíamos deshabilitar
extends
ylinterOptions
en anulaciones- probablemente también queremos rechazar
rulesDirectory
- ¿Queremos permitir
rules
yjsRules
en anulaciones o depreciamosjsRules
a favor de una anulación de**/*.js?(x)
?
También debería haber consenso de la gente de la organización palantirtech sobre esto antes de seguir adelante, ya que es una característica bastante importante.
Me encontré con esto yo mismo, y solo quiero expresar mi interés por este tipo de función.
Terminamos relajando algunas reglas que afectan el código de producción y veamos cómo funciona. ):
Me encantaría ver esta característica
suscribirse - También necesita esto.
Necesito esto tanto :(
¡Aquí igual! Estamos usando mecanografiado con Vuejs y nuestros archivos de prueba unitaria no están juntos en un directorio de pruebas sino en todas partes a lo largo del código fuente del componente.
Me encantaría ver esta función, actualmente estamos usando una configuración un poco inestable que da como resultado que vscode resalte diferentes errores de pelusa de lo que resalta nuestra línea de comando lint para solucionar este problema.
Dudo mucho que esta característica se implemente alguna vez, tslint no parece mantenerse activamente en general. Sugiero cambiar a @typescript-eslint
, obtuvo soporte completo de los proyectos eslint y ts y la migración es más fácil que nunca con @ typescript-eslint / eslint-plugin-tslint . Y hay una tabla de compatibilidad con tslint y las correspondientes reglas de eslint / otras alternativas disponibles. La configuración de Eslint es altamente personalizable, por lo que no veo ningún punto para seguir con tslint.
Propongo aplicar el concepto de usos del repositorio git para archivos en .gitIgnore ... a las reglas tsLint. Uso de su posición jerárquica actual como contexto para el linter, junto con un archivo de anulación, al enlazar un subdirectorio en particular. Luego, puede incluir o excluir, configurar cualquier configuración en cualquier nivel de directorio que desee.
p.ej
Una configuración de tslint se coloca en la raíz, y en cualquier nivel particular de la estructura de su código fuente, le gustaría un comportamiento diferente, simplemente anótelo con un archivo tslint de extensión en la raíz de ese subdirectorio.
@redevill Ayuda a las personas a escribir pruebas en una carpeta test
. Pero ni una prueba de escritura como something.test.ts
en la misma carpeta del componente / servicio.
De acuerdo, pero con un cambio menor: (que podría automatizarse con el generador de plantillas (estilo CLI)
MyComponentDir
--- MyComponentTestsDir
------ tslint.test.json
------ algo.prueba.ts
--- mycomponent.component.css
--- mycomponent.component.html
--- mycomponent.component.ts
La idea aún podría funcionar.
Gran fan de esta propuesta. ¡SÍ, POR FAVOR! Mi preferencia sería el concepto Overrides.
Por cierto, dado el anuncio de desactivación de tslint, no puedo _realmente_ imaginar que se hará un cambio tan grande en esta etapa, y que mi equipo se mudará a eslint, que ya tiene funciones de anulación por regla + por archivo.
El anuncio antes mencionado: https://medium.com/palantir/tslint-in-2019-1a144c2317a9
@RoystonS tiene básicamente razón, una característica tan grande no se agregará a tslint en este momento. ver # 4534
Usamos un proyecto Angular. Necesitamos el concepto de anulaciones. De lo contrario, es doloroso manejar
Comentario más útil
El anidamiento no resuelve los problemas discutidos aquí. Muchas personas quieren que sus pruebas en la misma estructura de directorio que el código se pone a prueba, y simplemente no hay buena manera de hacer eso con tslint en este momento.