Lo que parecen necesitar es un analizador para su lenguaje (Java) y un nombre y tipo resolver. ("Generador de tablas de símbolos").
Después de analizar el texto de origen, un compilador generalmente tiene un nombre de resolución, que intenta registrar la definición de nombres y sus tipos correspondientes, y un verificador de tipos, que verifica que cada expresión tenga un tipo válido.
Normalmente el nombre/tipo resolver se queja cuando no puede encontrar una definición. Lo que quiere hacer es encontrar el elemento "indefinido" que está causando el problema e inferir un tipo para él.
Para
IPerson p = new Person();
la resolución de nombres sabe que "Persona" y "IPerson" no están definidos. Si se tratara de
Foo p = new Bar();
no habría ninguna pista que quería una interfaz, sólo que Foo es una especie de matriz abstracta de barra (por ejemplo, una clase o una interfaz). Por lo tanto, la herramienta debe saber qué decisión es la suya ("siempre que encuentre una construcción así, suponga que Foo es una interfaz ..."). Podría usar una heurística: IFoo y Foo significan que IFoo debería ser una interfaz, y en algún lugar alguien tiene que definir a Foo como una clase que se da cuenta de esa interfaz. Una vez que la herramienta ha tomado esta decisión, tendría que actualizar sus tablas de símbolos para que pueda pasar a otras declaraciones:
Para
p.Name = "Sklivvz";
dado que p debe ser una interfaz (por el inferencia anterior), entonces Name debe ser un miembro del campo, y parece que su tipo es String de la asignación.
Con eso, la declaración:
Assert.AreEqual("Sklivvz", p.Name);
nombres y tipos resuelven sin más problema.
El contenido de las entidades IFoo y Foo depende de usted; no tenías que usar get y set pero ese es tu gusto personal.
Esto no funcionará tan bien cuando tiene varias entidades en la misma declaración:
x = p.a + p.b ;
Sabemos que ayb son los dominios que podrían, pero no se puede adivinar qué tipo numérico si es que son numérico, o si son cadenas (esto es legal para cadenas en Java, no sé sobre C#). Para C++ ni siquiera sabes lo que significa "+"; podría ser un operador en la clase Bar. Entonces, lo que tiene que hacer es recopilar restricciones, por ejemplo, "a es un número indefinido o una cadena", etc. y a medida que la herramienta recolecta evidencia, reduce el conjunto de posibles restricciones. (Esto funciona como esos problemas planteados: "Joe tiene siete hijos. Jeff es más alto que Sam. Harry no puede esconderse detrás de Sam. ... ¿quién es el gemelo de Jeff?" Donde tiene que reunir la evidencia y eliminar las imposibilidades). También debe preocuparse por el caso en el que termina con una contradicción.
Puede descartar el caso p.a + p.b, pero no puede escribir las pruebas de su unidad con total impunidad. Hay solucionadores de restricciones estándar por ahí si quieres impunidad. (Que concepto)
OK, tenemos las ideas, ahora, ¿se puede hacer esto de una manera práctica?
La primera parte de este requiere un analizador y un nombre y tipo flexible resolver. Necesita un solucionador de restricciones o al menos una operación de "valores de valor definidos para un valor indefinido" (solucionador de restricciones triviales).
Nuestra DMS Software Reengineering Toolkit con su Java Front End probablemente podría hacer esto. DMS es una herramienta de creación de herramientas para personas que desean crear herramientas que procesen idiomas de forma arbitraria. (Piense en "calcular con fragmentos de programa en lugar de números").
DMS ofrece máquinas de análisis de uso general, y pueden construir un árbol por cualquier extremo delantero se le da (por ejemplo, Java, y hay una # delante extremo C). La razón por la que elegí Java es que nuestra interfaz Java tiene todo ese nombre y la maquinaria de resolución de tipo, y se proporciona en forma de fuente para que pueda ser doblada. Si te mantienes en el solucionador de restricciones triviales, probablemente puedas doblar la resolución del nombre de Java para descubrir los tipos. DMS le permitirá ensamblar árboles que corresponden a fragmentos de código, y combinarlos en otros más grandes; a medida que su herramienta recopile datos para la tabla de símbolos, podría construir los árboles primitivos.
En algún lugar, debe decidir que ha terminado. ¿Cuántas pruebas unitarias debe ver la herramienta antes de conocer toda la interfaz? (¿Supongo que se come todas las que le das?). Una vez completo, ensambla los fragmentos para los distintos miembros y crea un AST para una interfaz; DMS puede usar su impresora bonita para convertir ese AST nuevamente en código fuente como lo ha demostrado.
puedo sugerir Java aquí porque nuestro extremo frontal Java tiene nombre y tipo de resolución. Nuestra parte frontal C# no. Esta es una "mera" cuestión de ambición; alguien tiene que escribir uno, pero eso es bastante trabajo (al menos fue para Java y no puedo imaginar que C# sea realmente diferente).
Pero la idea funciona bien en principio usando DMS.
usted puede hacer esto con un poco de otras infraestructuras que daba acceso a un analizador y un nombre flexible y tipo de resolución. Eso podría no ser tan fácil de obtener para C#; Sospecho que MS puede darte un analizador y acceso a nombre y tipo de resolución, pero no hay forma de cambiar eso. Quizás Mono es la respuesta?
usted todavía necesita un fue generar fragmentos de código y ensamblarlos. Puede intentar hacer esto pirateando cuerdas; mi (larga) experiencia con el pegado de bits del programa es que si lo haces con cadenas, eventualmente lo arruinas. Realmente quieres piezas que representen fragmentos de código de tipo conocido, que solo se puedan combinar de forma que permita la gramática; DMS lo hace así sin ensuciar.
Puede hacerlo con una [plantilla T4.] (Http://msdn.microsoft.com/en-us/library/bb126445.aspx) No tengo una muestra útil, pero podría intentar escribir uno, si estás interesado. Pude ver cómo esto podría ser realmente útil en el desarrollo Test-First (TDD); el truco es compilar su código mientras escribe pruebas para métodos que aún no existen. El otro problema, por supuesto, es que la Plantilla T4 probablemente necesite ser más inteligente que lo que describió, y dudo que haya proporcionado una especificación completa en su ejemplo. –
@RobertHarvey, estaba discutiendo esto con un compañero de trabajo, y él tiene la impresión de que podría haber demasiada inferencia por hacer. Estaría feliz con algo que funciona de una manera significativamente más inteligente que la locura actual del "clic derecho" :-) – Sklivvz