diff --git a/.changeset/lovely-months-type.md b/.changeset/lovely-months-type.md new file mode 100644 index 00000000..8267b18d --- /dev/null +++ b/.changeset/lovely-months-type.md @@ -0,0 +1,5 @@ +--- +'@0no-co/graphqlsp': patch +--- + +Correctly replace with identical replacement strings diff --git a/packages/example/src/Pokemon.ts b/packages/example/src/Pokemon.ts index 653314be..716a83bb 100644 --- a/packages/example/src/Pokemon.ts +++ b/packages/example/src/Pokemon.ts @@ -20,7 +20,7 @@ export const WeakFields = gql` weaknesses someUnknownField } -` as typeof import('./Pokemon.generated').WeaknessFieldsFragmentDoc; +` as typeof import('./Pokemon.generated').PokemonFieldsFragmentDoc; export const Pokemon = (data: any) => { const pokemon = useFragment(PokemonFields, data); diff --git a/packages/graphqlsp/src/diagnostics.ts b/packages/graphqlsp/src/diagnostics.ts index 56954e73..1da51a67 100644 --- a/packages/graphqlsp/src/diagnostics.ts +++ b/packages/graphqlsp/src/diagnostics.ts @@ -375,7 +375,10 @@ export function getGraphQLDiagnostics( imp = imp.slice(4); // We remove the \n imp = imp.substring(0, imp.length - 1); - text = sourceText.replace(typeImport.getText(), imp); + const from = node.getStart(); + text = + sourceText.slice(0, from) + + sourceText.slice(from).replace(typeImport.getText(), imp); span.length = imp.length + ((oldExportName || '').length - exportName.length); } else { diff --git a/test/e2e/fixture-project/fixtures/rename-complex.ts b/test/e2e/fixture-project/fixtures/rename-complex.ts new file mode 100644 index 00000000..4fd96c3a --- /dev/null +++ b/test/e2e/fixture-project/fixtures/rename-complex.ts @@ -0,0 +1,13 @@ +import { gql } from '@urql/core'; + +export const PostFields = gql` + fragment PostFields on Post { + id + } +` as typeof import('./rename-complex.generated').PostFieldsFragmentDoc; + +export const Post2Fields = gql` + fragment Post2Fields on Post { + title + } +` as typeof import('./rename-complex.generated').PostFieldsFragmentDoc; diff --git a/test/e2e/generate-types.test.ts b/test/e2e/generate-types.test.ts index 63aa6cf6..1fedd10d 100644 --- a/test/e2e/generate-types.test.ts +++ b/test/e2e/generate-types.test.ts @@ -11,7 +11,9 @@ const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); const projectPath = path.resolve(__dirname, 'fixture-project'); describe('Type-generation', () => { const outFile = path.join(projectPath, 'rename.ts'); + const outFileComplex = path.join(projectPath, 'rename-complex.ts'); const genFile = path.join(projectPath, 'rename.generated.ts'); + const genFileComplex = path.join(projectPath, 'rename-complex.generated.ts'); const baseGenFile = path.join(projectPath, '__generated__/baseGraphQLSP.ts'); let server: TSServer; @@ -22,7 +24,9 @@ describe('Type-generation', () => { afterAll(() => { try { fs.unlinkSync(outFile); + fs.unlinkSync(outFileComplex); fs.unlinkSync(genFile); + fs.unlinkSync(genFileComplex); fs.unlinkSync(baseGenFile); } catch {} }); @@ -93,4 +97,39 @@ describe('Type-generation', () => { ); }); }, 20000); + + it('gets renamed correctly (complex)', async () => { + server.sendCommand('open', { + file: outFileComplex, + fileContent: '// empty', + scriptKindName: 'TS', + } satisfies ts.server.protocol.OpenRequestArgs); + + server.sendCommand('updateOpen', { + openFiles: [ + { + file: outFileComplex, + fileContent: fs.readFileSync( + path.join(projectPath, 'fixtures/rename-complex.ts'), + 'utf-8' + ), + }, + ], + } satisfies ts.server.protocol.UpdateOpenRequestArgs); + + server.sendCommand('saveto', { + file: outFileComplex, + tmpfile: outFileComplex, + } satisfies ts.server.protocol.SavetoRequestArgs); + + await waitForExpect(() => { + const contents = fs.readFileSync(outFileComplex, 'utf-8'); + expect(contents).toContain(` id + } +\` as typeof import('./rename-complex.generated').PostFieldsFragmentDoc`); + expect(contents).toContain(` title + } +\` as typeof import('./rename-complex.generated').Post2FieldsFragmentDoc`); + }); + }, 20000); });